in WCF

WCF – Handling Errors – Part 2

In my last post, we saw how we can handle Errors using FaultContracts and FaultExceptions. WCF framework is always extendable and thus we can extend the behavior of a service too. This leads us to the question – “So, Can I extend the service to accept all the Exceptions and possibly send back some meaningful exceptions based on the Exception to the client?”

Yes, sure we can! We can make use of IErrorHandler to handle Exceptions and create our own custom error messages, and then we can extend the behavior of the service using IServiceBehavior to pump in this custom error handler. Cool, so how it is done?

1) We first create our custom error handler which is derived from IErrorHandler

   1: public class ServiceGlobalExceptionHandler
   2:                               : IErrorHandler
   3: {
   4: 
   5: /// <summary>
   6: /// HandleError. Log an error, then allow the error to be handled as usual.
   7: /// </summary>
   8: /// <param name="ex"></param>
   9: /// <returns></returns>
  10: public bool HandleError(Exception ex)
  11: {
  12:     // Log the exception
  13:     // Return true to indicate the Exception has been handled
  14:     return true;
  15: }
  16: 
  17: /// <summary>
  18: /// Provide a fault. The MessageFault fault parameter can be replaced 
  19: /// or set to null to suppress reporting a fault. 
  20: /// </summary>
  21: /// <param name="error"></param>
  22: /// <param name="version"></param>
  23: /// <param name="fault"></param>
  24: public void ProvideFault(Exception error, MessageVersion version,
  25:                      ref System.ServiceModel.Channels.Message fault)
  26: {
  27:     // You can set the fault to something more meaningful to the client.
  28:     // Client's can handle this fault without the channel faulting
  29: 
  30:     //Decide whether to provide a fault.Shield the unknown exception
  31: }

2) Next we create an attribute which will add this custom error handler into the service’s error handlers

(For a clear understanding, I would recommend to download the code sample which is at the end of this post)

   1: public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
   2: {
   3:     Type _errorHandlerType;
   4: 
   5:     public ErrorBehaviorAttribute(Type errorHandlerType)
   6:     {
   7:         this._errorHandlerType = errorHandlerType;
   8:     }
   9:
  10:     .......
  11:     .......
  12: 
  13:     void IServiceBehavior.ApplyDispatchBehavior
  14:         (ServiceDescription description,
  15:          ServiceHostBase serviceHostBase)
  16:     {
  17:         IErrorHandler errorHandler;
  18: 
  19:         try
  20:         {
  21:             errorHandler
  22:                 = (IErrorHandler)Activator
  23:                        .CreateInstance(_errorHandlerType);
  24:         }
  25:         catch (MissingMethodException e)
  26:         {
  27:             throw new
  28:               ArgumentException("The errorHandlerType must have a public empty constructor.", e);
  29:         }
  30:         catch (InvalidCastException e)
  31:         {
  32:             throw new
  33:               ArgumentException("The errorHandlerType must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
  34:         }
  35:
  36:         foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
  37:         {
  38:             ChannelDispatcher channelDispatcher
  39:                  = channelDispatcherBase as ChannelDispatcher;
  40:             channelDispatcher
  41:                 .ErrorHandlers
  42:                 .Add(errorHandler);
  43:         }
  44:     }
  45: }

3) We now inform our service that this is the error behavior you have to look for

   1: [ServiceBehavior]
   2: [ErrorBehavior(typeof(ServiceGlobalExceptionHandler))]
   3: public class MyService : IMyService
   4: {
   5: .....
   6: .....
   7: }

 

Great! Now we have a common place where you can handle the exceptions! 🙂

So now our WCF project architecture changes a bit to include this global error handler

image

You can download the code sample below:

 

Write a Comment

Comment

Time limit is exhausted. Please reload the CAPTCHA.