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