IEndpointBehavior life cycle / logging service calls
<p>I'm trying to log all outbound requests that go to service references, including the full request and response body.  I thought I had a solution using behaviorExtensions but, after deploying, it became clear that the extension was shared between multiple requests.</p>

<p>Here's my current code:</p>

<pre class="lang-cs prettyprint-override"><code>public class LoggingBehaviorExtender : BehaviorExtensionElement
{
    public override Type BehaviorType =&gt; typeof(LoggingRequestExtender);
    protected override object CreateBehavior() { return new LoggingRequestExtender(); }
}

public class LoggingRequestExtender : IClientMessageInspector, IEndpointBehavior
{
    public string Request { get; private set; }
    public string Response { get; private set; }

    #region IClientMessageInspector

    public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
    {
        Request = request.ToString();
        Response = null;
        return null;
    }
    public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {
        Response = reply.ToString();
    }

    #endregion

    #region IEndpointBehavior

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(this);
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }

    public void Validate(ServiceEndpoint endpoint) { }

    #endregion
}
</code></pre>

<p>Then, when I reach the point to log, I extract the behavior...</p>

<pre class="lang-cs prettyprint-override"><code>var lre = client.Endpoint.Behaviors.OfType&lt;LoggingRequestExtender&gt;().FirstOrDefault();
var req = lre?.Request;
var resp = lre?.Response;
</code></pre>

<p>Adding debugging logging to the LoggingRequestExtender, I found it was only instantiated once for multiple requests.</p>

<p>Is there a way to make sure this behavior class is instantiated fresh for each thread?  Or is there a better way of getting the full request / response body when making service calls?</p>

<p><strong>Edit / Partial answer:</strong></p>

<p>Since writing this I have discovered that the value returned by BeforeSendRequest is passed into AfterReceiveReply as the correlationState so I can connect the request and response using a guid:</p>

<pre class="lang-cs prettyprint-override"><code>public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
    var guid = Guid.NewGuid();
    WebServiceLog.LogCallStart(guid, channel.RemoteAddress.ToString(), request.ToString());
    return guid;
}

public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
    Guid guid = (Guid)correlationState;
    WebServiceLog.LogCallEnd(guid, reply.ToString());
}
</code></pre>

<p>I see two flaws to this approach.  One, which is livable, is that this requires a log insert and then update rather than a single insert.</p>

<p>The second is more of an issue: In the case of an exception (e.g. timeout), we never hit AfterRecieveSupply so the log doesn't know what happened.  I can separately log the exception...</p>

<pre class="lang-cs prettyprint-override"><code>try
{
    response = client.SomeFunction(request);
}
catch (Exception ex)
{
    AppLog.Error("Some function failed", ex);
}
</code></pre>

<p>... but I can't see a way of accessing the guid outside of BeforeSendRequest / AfterReceiveReply so I have nothing to tie the exception log to the service request log.</p>