WCF Exception Handling with PostSharp

2 commentsWritten on May 23rd, 2008 by
Categories: Aspect Oriented Programming, PostSharp, WCF

In your WCF service methods, you should always provide proper exception handling. The exception handling code is almost always the same, so it's usually just copy/pasted in each method. Here's an example of a typical service method:

        public void PersistOrder(Order order)

        {

            try

            {

                Container.Resolve<IPersistOrderHandler>().Handle(order);

            }

            catch (BusinessException b)

            {

                throw new FaultException<BusinessExceptionInformation>(new BusinessExceptionInformation(b),

                    new FaultReason(b.Message));  

            }

            catch (FaultException)

            {

                throw;

            }

            catch (Exception e)

            {

                Container.Resolve<ILogger>().LogException(e);

                throw new FaultException(new FaultReason(e.Message));

            }

        }

That's a lot of code, even though only ONE line will differ from the other service methods in this service. Let's clean up this mess, shall we? Exception handling is a cross cutting concern so we might as well put it in one place (at least, one place for each different kind of exception handling that you need). We'll use PostSharp to define an ApplyServiceExceptionHandling aspect:

    [Serializable]

    public class ApplyServiceExceptionHandling : OnExceptionAspect

    {

        public override void OnException(MethodExecutionEventArgs eventArgs)

        {

            if (eventArgs.Exception is BusinessException)

            {

                throw new FaultException<BusinessExceptionInformation>(

                    new BusinessExceptionInformation(eventArgs.Exception as BusinessException),

                    new FaultReason(eventArgs.Exception.Message));

            }

            else if (eventArgs.Exception is FaultException)

            {

                eventArgs.FlowBehavior = FlowBehavior.RethrowException;

            }

            else

            {

                Container.Resolve<ILogger>().LogException(eventArgs.Exception);

                throw new FaultException(new FaultReason(eventArgs.Exception.Message));

            }

        }

    }

And now we can modify the earlier service method to this:

        [ApplyServiceExceptionHandling]

        public void PersistOrder(Order order)

        {

            Container.Resolve<IPersistOrderHandler>().Handle(order);

        }

That's a lot cleaner than the previous version right? Actually, this service has more than one service method so we're better off moving the ApplyServiceExceptionHandling attribute to the class level instead of the method level:

    [ApplyServiceExceptionHandling]

    public class OrderManagementService : IOrderManagementService

now we can get rid of all of the exception handling code in each service method, but each one will have exception handling applied to it because the exception handling aspect is applied to the class, and thus, to each method of that class. And if you need to modify your exception handling (to handle TargetInvocationExceptions with BusinessExceptions as InnerExceptions for instance?) you'd only have to do this in one place.

Btw, i'm aware of WCF's IErrorHandler interface (which allows you to handle exceptions in a general manner as well)... i just don't like it :)

  • SaumonAgile

    Thanks, it is exactly what I was looking for :)

  • http://twitter.com/DavidKomar David KOMAR

    Thanks a lot, exactly what I needed