IEndpointBehavior Lifecycle Service Calls

I am trying to register all outgoing requests that go to service links, including the full request and the response body. I thought I had a solution using actionsExtensions, but after deployment it became clear that the extension was shared between several requests.

Here is my current code:

public class LoggingBehaviorExtender : BehaviorExtensionElement
{
    public override Type BehaviorType => 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
}

Then, when I get to the log point, I retrieve the behavior ...

var lre = client.Endpoint.Behaviors.OfType<LoggingRequestExtender>().FirstOrDefault();
var req = lre?.Request;
var resp = lre?.Response;

Adding a debug log to LoggingRequestExtender, I found that it was created only once for several requests.

Is there a way to make sure that this behavior class is created for each thread? Or is there a better way to get a complete request / response authority when making service calls?

Edit / Partial Answer:

, , BeforeSendRequest, AfterReceiveReply , guid:

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());
}

. , , , , , .

: (, timeout) AfterRecieveSupply, , . ...

try
{
    response = client.SomeFunction(request);
}
catch (Exception ex)
{
    AppLog.Error("Some function failed", ex);
}

... BeforeSendRequest/AfterReceiveReply, .

+4
1

.

1. , , , . WCF , MemoryCache Guid . , . , , MemoryCache x , ( ).

WCF , , , , , sql.

2. , ? , . , IDisposable, , .

RequestMessage request = new RequestMessage();  
ResponseMessage response = null;

using (_messageLogger.LogMessage(request, () => response, CallContextHelper.GetContextId(), enabled))
{
  response = _outboundService.DoSomething(request);  
}

-, dispose.

, , , ...

0

Source: https://habr.com/ru/post/1649475/


All Articles