WCF Error Handling

For the last few posts I was focusing on logging from a Windows Azure Hosted Service. When implementing a WCF service, a common problem that I see is the lack of unhandled exception logging. This seems to be a feature that slips through the cracks until an application goes into production. I for one don’t blame the development teams for overlooking this because implementing this feature in WCF is no easy task.

So, here is a basic implementation of an error handling behaviour for WCF that can be re-used for multiple projects.

IErrorHandler

To start with, we will create a class that implements the IErrorHandler interface. This class will be in charge of sending the unhandled exceptions to log4net.

public class ErrorHandler : IErrorHandler
{
    private ILog _logger;
    public ErrorHandler()
    {
        _logger = LogManager.GetLogger(GetType());
    }

    public bool HandleError(Exception error)
    {
        _logger.Error(error.Message, error);
        return false;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
    }
}

The false return value indicates that WCF should abort the session, if true was returned the session would be kept alive.

ErrorHandlingBehavior

Once we have the error handler we need to attach it to the channel dispatcher. To accomplish this we need to write a behaviour. Note, this implementation inherits from Attribute so that this can be added to a service contract as an attribute. Later I will show how to configure the behaviour with the web.config file.

public class ErrorHandlingBehavior : Attribute, IServiceBehavior
{
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        var errorHandler = new ErrorHandler();
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
        {
            channelDispatcher.ErrorHandlers.Add(errorHandler);
        }
    }

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }
}

Now if we stop the implementation here we can add this as an attribute to any service contract.

ErrorHandlingBehaviorExtension and web.config

The attribute may be a simple solution, however you may want to implement error handling on all the services without needing to modify each one. To accomplish this, you can use the default behaviour feature in .NET 4.0.

<system.serviceModel>   <extensions>     <behaviorExtensions>       <add name="ErrorLogging" type="WebService.ErrorLogging.ErrorHandlingBehaviorExtension, WebService" /> 
     </behaviorExtensions>   </extensions>   <behaviors>     <serviceBehaviors>       <behavior>         <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->         <serviceMetadata httpGetEnabled="true"/>         <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->         <serviceDebug includeExceptionDetailInFaults="false"/>         <ErrorLogging />       </behavior>     </serviceBehaviors>   </behaviors>   <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel>
namespace WebService.ErrorHandling
{
    public class ErrorHandlingBehaviorExtension : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof(ErrorHandlingBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new ErrorHandlingBehavior();
        }
    }
}

Well that should just about do it. Implementing these three classes will allow you to configure error logging for WCF services, including WCF HTTP services.

Thank you.