title: How to log http level stream from WCF SOAP client on .NET Core?
body: <p>Background: I'm maintaining an integration platform that pulls data from various unreliable APIs. Some of those actions generate potentially high costs, so for diagnostic purposes, every outgoing and incoming message is logged to disk to a separate file. For REST-like APIs, I use a simple wrapper on the network stream that also saves data to a file. For <strong>.NET Classic</strong> SOAP client, I have a helper that dynamically wraps <code>SoapHttpClientProtocol</code> to use the same network stream logging mechanism.</p>
  
  <p>With <strong>.NET Standard 2.0</strong> and <strong>.NET Core</strong>, the only supported way to write SOAP clients is WCF. How do I <strong>programmatically</strong> configure WCF SOAP client to log the HTTP incoming/outgoing streams to separate files, preferrably with configurable names?</p>
  
  <p>My current sample client code:</p>
  
  <pre><code>public abstract class ServiceCommunicatorBase&lt;T&gt;
      where T : IClientChannel
  {
      private const int Timeout = 20000;
  
      private static readonly ChannelFactory&lt;T&gt; ChannelFactory = new ChannelFactory&lt;T&gt;(
          new BasicHttpBinding(),
          new EndpointAddress(new Uri("http://target/endpoint")));
  
      protected T1 ExecuteWithTimeoutBudget&lt;T1&gt;(
          Func&lt;T, Task&lt;T1&gt;&gt; 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(() =&gt; serviceCall(service)).GetAwaiter().GetResult();
          }
      }
  
      private T CreateService(int timeout)
      {
          var clientChannel = ChannelFactory.CreateChannel();
          clientChannel.OperationTimeout = TimeSpan.FromMilliseconds(timeout);
          return clientChannel;
      }
  }
  
  public class ConcreteCommunicator
      : ServiceCommunicatorBase&lt;IWCFRemoteInterface&gt;
  {
      public Response SomeRemoteAction(Request request)
      {
          return this.ExecuteWithTimeoutBudget(
              s =&gt; s.SomeRemoteAction(request));
      }
  }
  </code></pre>