In my previous post, I showed my implementation for logging outgoing HTTP requests. In this post, I’ll show my implementation for logging outgoing SOAP requests using custom endpoint behaviour.
First I have an implemention of the IClientMessageInspector. IMessageLoggingInspector is mainly for DI.
public interface IMessageLoggingInspector : IClientMessageInspector { } public class MessageLoggingInspector : IMessageLoggingInspector { // AfterReceiveReply is called when the response is received. public void AfterReceiveReply(ref Message reply, object correlationState) { string messageContent = CopyAndGetMessageContent(ref reply); var message = new { Id = correlationState, Response = messageContent }; // Code to log response message goes here } // BeforeSendRequest is called before the request is sent. This is where the request should be logged. public object BeforeSendRequest(ref Message request, IClientChannel channel) { var messageContent = CopyAndGetMessageContent(ref request); var requestId = Guid.NewGuid(); var message = new { Id = requestId, Body = messageContent, RequestDate = DateTime.UtcNow }; // Code to log message goes here // Whatever returned here will be the correlationState in AfterReceiveReply method above. // You need this to track which response is correlated to a request. return requestId; } private static string CopyAndGetMessageContent(ref Message request) { var buffer = request.CreateBufferedCopy(int.MaxValue); // Create a copy and set it back to request // because as soon as the request is read, you cannot read it again. request = buffer.CreateMessage(); var originalMessage = buffer.CreateMessage(); string messageContent; using (var stringWriter = new StringWriter()) { using (var xmlTextWriter = new XmlTextWriter(stringWriter)) { originalMessage.WriteMessage(xmlTextWriter); xmlTextWriter.Flush(); xmlTextWriter.Close(); } messageContent = stringWriter.ToString(); } return messageContent; } }
Then I need to implement IEndpointBehavior.
public interface IMessageLoggingBehaviour : IEndpointBehavior { } public class MessageLoggingBehaviour : IMessageLoggingBehaviour { private readonly IMessageLoggingInspector _messageLoggingInspector; public MessageLoggingBehaviour(IMessageLoggingInspector messageLoggingInspector) { _messageLoggingInspector = messageLoggingInspector; } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.ClientMessageInspectors.Add(_messageLoggingInspector); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } }
Finally, I just need to add MessageLoggingBehaviour when I create a SOAP client
public class SoapClientFactory { private readonly IMessageLoggingBehaviour _messageLoggingBehaviour; public SoapClientFactory(IMessageLoggingBehaviour messageLoggingBehaviour) { _messageLoggingBehaviour = messageLoggingBehaviour; } public SomeSampleSoapClient GetSampleSoapClient() { var sampleSoapClient = new SomeSampleSoapClient(); // More endpoint settings and behaviours go here // Add messageLoggingBehaviour as the last EndpointBehavior client.Endpoint.EndpointBehaviors.Add(messageLoggingBehaviour); } }