WCF, IErrorHandler and propagating faults

On a recent project, I have needed to set up a generic error handler just above the service layer which ensured that only known exceptions were propagated up to the client in a controlled manner. This post contains information about how to write an IErrorHandler, but more importantly, it does contain an important point at the end about its implementation that I wanted to share, as well as save for my own reference on this blog, in this wonderful inter-web thingy.

Update: The code for this article is here

Using FaultContracts is a good way of achieving this WCF, but I also wanted to be able to:

  • Catch generic CLR exceptions and propagate them to the client as a generic fault exceptions.
  • Catch some NHibernate specific exceptions (the concurrency ones in particular) and propagate these to the client as a general concurrency fault.

This was all the client needed to know, and also provided an opportunity to log any unhandled exceptions that may sneak there way up to the services. WCF provides great exception shielding by default, but we wanted a bit more control.

Enter the IErrorHandler interface that allows you to intercept any faults or exceptions before they are sent back to the client. To use this properly, you still need to define your FaultContract as required. My simple example contract is as follows:

image

So to start the implementation of my custom error handler, I define a class that  will implement an IErrorHandler as well as IServiceBehavior.

image

I do this because not only do I want to create an IErrorHandler implementation, but I need it to participate as a behavior within the WCF pipeline, that is, I want to add it in as a ServiceBehavior when I create the host so that my custom error handler implementation can be plugged in.

I first provide implementations for the IErrorHandler.

image

HandleError returning true simply means I have handled this error and don't need other error handlers to deal with it.

ProvideFault does a few things. First it checks if its a genuine FaultException. If so, it does nothing but let it pass through. If it isn't, then a FaultException<ApplicationFault> is created, and a message fault is generated from that. Then a new message is created, using the message fault is its content, and that message is assigned to the return fault parameter.

If I wanted to catch another type of exception, I might check for it something like:

if (error is NHibernate.StaleObjectException) .....

and optionally create a different type of fault. The ApplicationFault used to construct the FaultException is just a standard DataContract.

image

Implementing the IServiceBehavior is pretty easy as you see below:

image

If you wanted to, in the Validate method, you could iterate through each operation and ensure its got your required FaultContract applied like this:

image

As a nice touch, I wanted this error handler to be able to added via configuration and play nicely with the WCF Service Configuration editor. To do this, you need a class that inherits from BehaviorExtensionElement and implements 2 simple methods like this:

image

So, finally we are at the point that caught me up for a while. In the implementation of the ProvideFault method of my error handler, you need to specify an action for the returned Fault as shown below:

image

Now its important that this Action is a known action identifier that your client is expecting. In other words, if you generate a proxy (via SvcUtil) for this service and peek into the reference.cs file for the 'Action' attribute on your services fault contract, make sure they are the same. Otherwise, when your error handler generates a fault with an unknown fault action, the client wont accept it as a known fault and it will look like just a generic FaultException, not the specific FaultContract<YourType> you were after.

When I was developing this error handler, I simply fudged this value while I got on with the task of implementing the handler. I forgot about it, then spend some time wondering why my faults were not being propagated and caught properly on the client. So make sure you supply a well known action for your fault in the contract attribute and in the error handler like this:

First on your FaultContract attribute:

image

Then in your ProvideFault implementation:

image

So finally, thats it. Don't forget about matching up those actions, otherwise you'll waste your time.

Hope this has proved helpful and informative.

Update: The code for this article is here 

18 Comments

  • Hi,
    i am trying to do the exact same thing, implemented the ierrorhandler and iservice behaviour to an error handler class. But the provide fault method is not getting triggered when an unhandled exception pops up. I know i missed to configure something, thought u could help !

    -ronny

  • Hi ronny,
    Just sounds like your config is wrong. I would need to see it tho.

  • Thanks for the post, I'm still having some configuration problems, is it possible to get the source?

  • I am also having similar problems implimentuing this. I created my ErorHandler class, as well as an ErrorHandlerServiceBehaviorExtensionElement class so it will play nicely with the config tools.
    Do I need to impliment IServiceBehavior as well? Is the ServiceBehaviorExtensionElement class just a nicety that allows the config tools to recognize my stuff, or does having it and adding my error handler via an extension in the web.config file automatically load my error handler?

  • Can u provide the complete source code?

    I think I've implimented everything properly, but I am getting a CommunicationException instead of my FaultException back at the client.

  • Article is incomplete without the complete source code !

  • Okay everybody who wanted some code. I have placed some download links within the article above.

    Sorry for the delay, but I went on holidays and my care factor was at an all time low... :-)

  • Awesome ! You save me a lot of time !

  • source code is not reachable

  • jyfacb,

    Apologies. Should be working now.

  • Nice explanation, i was trying to achieve the same thing, but failed cause i wasnt setting a fixed "action" for faults. That solved my problem.

    Another thing, u can improve (as i already did): create a custom servicehost that dynamically adds ServiceBehavior to ServiceDescription's, and faults to OperarionDescription's. So you dont need to made those checkings int he "Validate" method.

  • Dude, this was *very* helpful. As an aside, I played a bit with it and found out that you can leave the Action as null:

    Just leave out the Action from the FaultContract attribute:
    [FaultContract(typeof(ApplicationFault)]

    and set the Action to null in the ProvideFault() method implementation:
    fault = Message.CreateMessage(version, msgFault, null);

    Setting the Action to a constant doesn't buy much and I can't find a reason why it can't be left as null

  • Man, you saved me a day, great job!

  • For supporting Services that have a combination of OneWay and TwoWay OperationContracts add the following logic to the inner foreach loopin void Validate:

    foreach (var svcEndpoint in serviceDescription.Endpoints)
    {
    if (svcEndpoint.Contract.Name != "IMetadataExchange")
    {
    foreach (var opDesc in svcEndpoint.Contract.Operations)
    {
    if (opDesc.IsOneWay)
    { // Ignore OneWay OperationContracts. OneWay operations cannot expose FaultContracts
    continue;
    }

  • Hey Petros,

    Good idea. Didn't consider the one way scenario.

  • Nice post, thanks for the info. However please consider using simple html markup for the code rather than images. It's very difficult to read, or follow, or copy/paste.

  • heyyy its a good example... thx

  • I damn near went blind trying to read your screen captures!!!!

Comments have been disabled for this content.