WCF – Logging Before and After Operation Invocation
0
Here’s another custom WCF EndpointBehavior I found useful recently.
Not content with logging all unhandled errors, I wanted to output a DEBUG level log message before and after every operation invocation. As before, I’m using the Castle Windsor Logging Facility to handle my logging, but you can swap that out for your logger of choice if required.
Firstly, here’s the EndPointBehaviour itself. This adds a custom CallContextInitializer to every service operation:
using System;
using System.ServiceModel.Description;
using Castle.Core.Logging;
/// <summary>
/// Being a custom EndpointBehavior added to the WCF services such that each operation outputs
/// a debug log message before and after invocation.
/// </summary>
public class OperationLoggingEndpointBehavior : IEndpointBehavior
{
private readonly ILogger logger;
public OperationLoggingEndpointBehavior(ILogger logger)
{
this.logger = logger;
}
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
foreach (var operation in endpointDispatcher.DispatchRuntime.Operations)
{
operation.CallContextInitializers.Add(new OperationLoggingCallContextInitializer(this.logger, operation.Name, endpoint.Contract.Name));
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
Here’s the custom CallContextInitializer:
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Castle.Core.Logging;
/// <summary>
/// Custom call context initializer added to all WCF operations such that each operation outputs
/// a log message before and after invocation.
/// </summary>
public class OperationLoggingCallContextInitializer : ICallContextInitializer
{
private readonly ILogger logger;
private readonly string operationName;
private readonly string contractName;
public OperationLoggingCallContextInitializer(ILogger logger, string operationName, string contractName)
{
this.logger = logger;
this.operationName = operationName;
this.contractName = contractName;
}
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
this.logger.DebugFormat("BeforeInvoke {0}.{1}", this.contractName, this.operationName);
return null;
}
public void AfterInvoke(object correlationState)
{
this.logger.DebugFormat("AfterInvoke {0}.{1}", this.contractName, this.operationName);
}
}
And the Windsor configuration is much the same as last time:
container.Register(
Component.For<OperationLoggingEndpointBehavior>()
.Attribute("scope").Eq(WcfExtensionScope.Services));








