代码之家  ›  专栏  ›  技术社区  ›  skolima

如何在.NETCore上记录来自WCFSOAP客户端的http级流?

  •  1
  • skolima  · 技术社区  · 7 年前

    SOAP客户端,我有一个动态包装的助手 SoapHttpClientProtocol

    具有 .NET标准2.0 和 ,唯一受支持的编写SOAP客户端的方法是WCF。我该怎么办 以编程方式

    我当前的示例客户端代码:

    public abstract class ServiceCommunicatorBase<T>
        where T : IClientChannel
    {
        private const int Timeout = 20000;
    
        private static readonly ChannelFactory<T> ChannelFactory = new ChannelFactory<T>(
            new BasicHttpBinding(),
            new EndpointAddress(new Uri("http://target/endpoint")));
    
        protected T1 ExecuteWithTimeoutBudget<T1>(
            Func<T, Task<T1>> serviceCall,
            [CallerMemberName] string callerName = "")
        {
            // TODO: fixme, setup logging
            Console.WriteLine(callerName);
    
            using (var service = this.CreateService(Timeout))
            {
                // this uses 2 threads and is less than ideal, but legacy app can't handle async yet
                return Task.Run(() => serviceCall(service)).GetAwaiter().GetResult();
            }
        }
    
        private T CreateService(int timeout)
        {
            var clientChannel = ChannelFactory.CreateChannel();
            clientChannel.OperationTimeout = TimeSpan.FromMilliseconds(timeout);
            return clientChannel;
        }
    }
    
    public class ConcreteCommunicator
        : ServiceCommunicatorBase<IWCFRemoteInterface>
    {
        public Response SomeRemoteAction(Request request)
        {
            return this.ExecuteWithTimeoutBudget(
                s => s.SomeRemoteAction(request));
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  6
  •   skolima    7 年前

    我已设法使用 IClientMessageInspector 通过可配置的行为连接。有 一些 Message Inspectors on MSDN netstandard-2.0

    我不得不放弃使用手机 ChannelFactory<T> 使用实际生成的代理类。工作代码(为简洁起见进行了裁剪):

    var clientChannel = new GeneratedProxyClient(
      new BasicHttpBinding { SendTimeout = TimeSpan.FromMilliseconds(timeout) },
      new EndpointAddress(new Uri("http://actual-service-address"));
    
    clientChannel.Endpoint.EndpointBehaviors.Add(new LoggingBehaviour());
    

    服务类别:

    // needed to bind the inspector to the client channel
    // other methods are empty
    internal class LoggingBehaviour : IEndpointBehavior
    {
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(new LoggingClientMessageInspector());
        }
    }
    
    internal class LoggingClientMessageInspector : IClientMessageInspector
    {
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            var correlationId = Guid.NewGuid();
            this.SaveLog(ref request, correlationId, "RQ");
    
            return correlationId;
        }
    
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            var correlationId = (Guid)correlationState;
            this.SaveLog(ref reply, correlationId, "RS");
        }
    
        private void SaveLog(ref Message request, Guid correlationId, string suffix)
        {
            var outputPath = GetSavePath(suffix, correlationId, someOtherData);
            using (var buffer = request.CreateBufferedCopy(int.MaxValue))
            {
                var directoryName = Path.GetDirectoryName(outputPath);
                if (directoryName != null)
                {
                    Directory.CreateDirectory(directoryName);
                }
    
                using (var stream = File.OpenWrite(outputPath))
                {
                    using (var message = buffer.CreateMessage())
                    {
                        using (var writer = XmlWriter.Create(stream))
                        {
                            message.WriteMessage(writer);
                        }
                    }
                }
    
                request = buffer.CreateMessage();
            }
        }
    }