Ludovic Beauquel

Writing on ASP.NET, C#, .NET, Microsoft.

Getting Elmah to work with WCF services hosted in IIS

leave a comment »


If you are using the great Elmah error logger in your web application you have probably noticed that errors raised within the WCF service are not logged with Elmah.

We are going to bridge the gap by creating a library that will log WCF exceptions into Elmah.

Let’s create a new class library project in Visual Studio

Then Add the “Elmah Core Library (no config)” using NuGet.

Manage NuGet Packages...

NuGet ELMAH Core Library

And add the two following references:

  • System.ServiceModel
  • System.Web

Add references to System.ServiceModel and System.Web

We will now add two classes to the project.

  • ElmahWCFErrorLogger that implements IErrorHandler interface that will extend the way WCF handles exceptions.
  • ServiceErrorBehaviorAttribute which allows you to plug your newly created error handleer into the WCF error-handling infrastructure.

ElmahWCFErrorLogger implementation:

using System;
using System.ServiceModel.Dispatcher;
using System.Web;

namespace ElmahWCF
{
    public class ElmahWCFErrorLogger : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return false;
        }

        public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
        {
            if (error == null)
                return;
            ///In case we run outside of IIS, 
            ///make sure aspNetCompatibilityEnabled="true" in web.config under system.serviceModel/serviceHostingEnvironment
            ///to be sure that HttpContext.Current is not null
            if (HttpContext.Current == null) 
                return;
            Elmah.ErrorSignal.FromCurrentContext().Raise(error);
        }
    }
}

ServiceErrorBehaviorAttribute implementation:

using System;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace ElmahWCF
{
    [AttributeUsage(AttributeTargets.Class)]
    public class ServiceErrorBehaviorAttribute : Attribute, IServiceBehavior
    {
        Type errorHandlerType;
        public ServiceErrorBehaviorAttribute(Type errorHandlerType)
        {
            this.errorHandlerType = errorHandlerType;
        }
        public void AddBindingParameters(ServiceDescription serviceDescription,
           System.ServiceModel.ServiceHostBase serviceHostBase,
           System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
           System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        { }
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler;
            errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
            foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher cd = cdb as ChannelDispatcher;
                cd.ErrorHandlers.Add(errorHandler);
            }
        }
        public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { }
    }
}

Last step: Compile the library, add a reference to that library in your web application that uses Elmah.

And use it in your WCF service implementation as following:

[ServiceErrorBehavior(typeof(ElmahWCFErrorLogger))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SampleWCFService : ISampleWCFService
{
    // Implementation omitted
}

Resources:

Getting ELMAH to work with WCF services

Written by Ludovic Beauquel

January 30, 2012 at 6:00 am

Posted in .NET, IIS, System, WCF

Leave a comment