WCF Global Exception Handling Attribute and IErrorHandler

Exception handling in WCF can clutter your code with the same error handling routine over and over again. This is especially true when you want to provide some meaningful, yet safe, FaultExceptions back to the client. Wouldn’t it be nice if we had a way to handle these kind of exceptions on a more global service scope?

In this example we have a basic WCF service called SomeService with one operation called SomeFailingOperation. We need to handle exceptions from all service operations by logging what went wrong. We also need to return a generic vague FaultException back to the client stating what operation failed.

To do this we need to create an ErrorHandler first by implementing the IErrorHandler interface found in the System.ServiceModel.Dispatcher namespace. The HandleError method enables error handling and returns true to abort the current session. The ProvideFault method is the place where we provide our custom FaultException for our client. This is also the spot to do some kind of error logging.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
 
namespace WcfService
{
    public class GlobalExceptionHandler : IErrorHandler
    {
        #region IErrorHandler Members
 
        public bool HandleError(Exception ex)
        {
            return true;
        }
 
        public void ProvideFault(Exception ex, MessageVersion version,
                                 ref Message msg)
        {
            // Do some logging here
 
            var newEx = new FaultException(
                string.Format("CALLED FROM YOUR GLOBAL EXCEPTION HANDLER BY {0}",
                              ex.TargetSite.Name));
 
            MessageFault msgFault = newEx.CreateMessageFault();
            msg = Message.CreateMessage(version, msgFault, newEx.Action);
        }
 
        #endregion
    }
}

Now we need to create a custom Service Behaviour Attribute to let WCF know that we want to use this global error handler whenever an exception occurs. We do this by deriving a class derived from Attribute and also implement the IServiceBehavior interface. In the constructor of this service behavior class we get the error handler type, like the one we showed here.

We only need to create this error handler once ApplyDispatchBehavior is called. In this method we can ‘inject’ our error handler. We do this by instantiating the handler with a call to Activator.CreateInstance and then add the newly created error handler to each channel dispatchers errorhandlers collection.

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
 
namespace WcfService
{
    public class GlobalExceptionHandlerBehaviourAttribute : Attribute, IServiceBehavior
    {
        private readonly Type _errorHandlerType;
 
        public GlobalExceptionHandlerBehaviourAttribute(Type errorHandlerType)
        {
            _errorHandlerType = errorHandlerType;
        }
 
        #region IServiceBehavior Members
 
        public void Validate(ServiceDescription description,
                             ServiceHostBase serviceHostBase)
        {
        }
 
        public void AddBindingParameters(ServiceDescription description,
                                         ServiceHostBase serviceHostBase,
                                         Collection<ServiceEndpoint> endpoints,
                                         BindingParameterCollection parameters)
        {
        }
 
        public void ApplyDispatchBehavior(ServiceDescription description,
                                          ServiceHostBase serviceHostBase)
        {
            var handler =
                (IErrorHandler) Activator.CreateInstance(_errorHandlerType);
 
            foreach (ChannelDispatcherBase dispatcherBase in 
                serviceHostBase.ChannelDispatchers)
            {
                var channelDispatcher = dispatcherBase as ChannelDispatcher;
                if (channelDispatcher != null)
                    channelDispatcher.ErrorHandlers.Add(handler);
            }
        }
 
        #endregion
    }
}

Finally, all we need to do is to decorate our Service class with our GlobalExceptionHandlerBehaviour attribute providing the type of our custom error handler and we are done.

using System;
 
namespace WcfService
{
    [GlobalExceptionHandlerBehaviour(typeof (GlobalExceptionHandler))]
    public class SomeService : ISomeService
    {
        #region ISomeService Members
 
        public string SomeFailingOperation()
        {
            throw new Exception("Kaboom");
            return null;
        }
 
        #endregion
    }
}

For each operation in our WCF service, whenever an exception is thrown, our global error handlers ProvideFault method is called and a custom FaultException is sent back to the client. So if we make a call to SomeFailingOperation…

WCF Global Exception Handling Error Handler Message

24 thoughts on “WCF Global Exception Handling Attribute and IErrorHandler

  1. hello Leon, im just wondering about the end
    throw new Exception(“Kaboom”);
    is that the return the client gets?

    and can i access that in
    public void ProvideFault(Exception ex, MessageVersion version,
    ref Message msg)

    for logging? :)
    thank you for this guide

    • Hey Mattias,

      ProvideFault can be a nice spot for logging indeed. The “Kaboom” Exception does not make it to the client by default. You can rewrite whatever you want report to your client in ProvideFault.

  2. I see that the
    public class GlobalExceptionHandlerBehaviourAttribute : Attribute, IServiceBehavior
    goes through the functions so i assume it adds the IErrorHandler gets installed?
    but it doesent catch any exeptions.
    please help! :)

    • The only thing I can think of right now is you forgot the attribute on the service implementation?

      [GlobalExceptionHandlerBehaviour(typeof (GlobalExceptionHandler))]

      But I guess you thought of that… :-|

      • hmmm it works when i take away the
        [OperationContract] from an operation
        but cant get an

        public string SomeFailingOperation()
        {
        throw new Exception(“Kaboom”);
        return null;
        }

        to work :/

      • it catched a exeption outside my funcions but cant get it to work within an function xD

  3. yes i have it on my class with functions
    [GlobalExceptionHandlerBehaviour(typeof(GlobalExceptionHandler))]
    public class Service : IService
    {
    public string SomeFailingOperation()
    {
    throw new Exception(“Kaboom”);
    return null;
    }
    }

    but im thinking if i have something wrong with the config file or does that affect this?

      • Was working all along xD but i didnt notice that in my testing because i didnt have the right settings for it…

        Go to Debug -> Exceptions and uncheck the checkbox under Thrown column for row CLR exception.

        If that checkbox is checked, it will cause the debugger to stop at every location where you are throwing exception.

  4. The ProvideFault method throws me the following error message
    “The type ‘System.Xml.XmlDictionaryReader’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′”.

    Could you please help me to undestand and solve this.?

  5. While i was doing overtime in my company, this useful post got my savior after spending so much time on web for a simple and chic solution.
    Congratulations Mr Leon..

  6. Hi
    I’m very new to WCF. Can you please tell me where to apply GlobalExceptionhandler?
    at server side or client side?

  7. Its not working for me either.
    Do we need to add “try catch block” on all methods of the class?
    Do we need to add some configuration in web.config?
    Whenever there is an exception cursor never hits ProivdeFault method nor to HandleError.

  8. With this process, it sends full exception details along with stacktrace to the client. Is there is a way to limit this so that only Faultexception gets passed to client?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>