none
Handling exceptions on server and client side RRS feed

  • Question

  • I need to propagate custom exceptions from the server side back to the client.  I have a DataContractSerializerSurrogate that can handle serializing custom properties on the exception, but even though I have applied to the surrogate to the operation, it does not seem to be used when creating fault messages.  To get around this, I implemented IErrorHandler and in ProvideFault, I serialize it myself and return a new FaultException<T> with the serialization info.  This works, but I'm hoping there's a better way to serialize the exception details than this.

     

    Secondly, I need to de-serialize and unwrap the FaultException<T> on the client side.  Is there a way to apply some sort of handler or behavior on the client side that will automatically catch the FaultException<T> on all responses so that I can process the exception and then re-throw my true custom exception?  I don't want to have to do the try/catch of FaultException<T> on each service call individually.

     

    Thanks,

    Carole

     

    Friday, April 25, 2008 11:45 PM

Answers

  • For completeness, I need to add that you'd also need to implement a custom IEndpointBehavior. It works like this:
     
     - Attach the custom message inspector mentioned in my previous post to the custom IEndpointBehavior in the ApplyClientBehavior method.
    Code Snippet

            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                // Add the custom message inspector
                clientRuntime.MessageInspectors.Add(new CustomMessageInspector());
            }

     

     - Add the endpoint behavior to the proxy:
    Code Snippet
    // attach the message inspector before opening
    proxy.ChannelFactory.Endpoint.Behaviors.Add(new CustomMessageInspectorEndpointBehavior());

     

     

    Monday, April 28, 2008 7:29 PM

All replies

  • Your approach with IErrorHandler is what worked for me.  A couple of pointers:
    http://blogs.msdn.com/drnick/archive/2007/01/24/modifying-http-error-codes-part-2.aspx
    http://blogs.microsoft.co.il/blogs/sasha/archive/2008/04/12/automatically-converting-exceptions-to-wcf-faults.aspx

    On the client-side, if you're strongly inclined against using FaultException<T>, I think you must provide a custom channel:
    http://blogs.msdn.com/drnick/archive/2006/12/28/consuming-faults-part-1.aspx

    It seems not worth the effort, IMHO, but suit yourself :-)
    Saturday, April 26, 2008 2:31 PM
  • Its recommend to keep teh FaultException<T> if you can. One way around having to wrap each call is to just wrap the methods in the a ClientBase<T>.  If you are using a proxy class, you will need to hack that code.  If you are using a ChannelFactory<T> you can build your own ClientBase<T> instead.  The ClientBase<T> class can inherit from your service interface in each of those methods just have a try catch that interpruts the FaultException and converts it into your custom exception.
    Monday, April 28, 2008 1:39 PM
    Moderator
  • Dan, I agree with you generally - if you want to maintain explicit boundaries, you wouldn't want to conceal the fact the exceptions were originally faults.  However, if I didn't care about explicit boundaries (e.g. if using WCF as an ORPC mechanism) I would certainly not go and wrap every method call manually, but use a FaultConverter.
    Monday, April 28, 2008 3:07 PM
  • Thanks for the helpful information.  It's good to know that I was on the right track on the server side.

     

    One of the reasons that I don't want to propagate the FaultException<T> back up on the client side is that the client does not necessarily know that it is running in a WCF environment.  It can be run completely in-process, or it can be run through a proxy to a WCF service host.  As Dan suggested, I could wrap each proxy call to pull out the exception (which is what I've done in my proof-of-concept test), but with about 40+ different service calls over 5 different services, I would like to plugin at a lower level to cleanly handle this in one location.

     

    I've looked at the custom channel/FaultConverter blog, but I haven't yet figured out how to get that to work with my setup.  I have my bindings (WsDualHttpBinding) and endpoints defined in a config file.  Somehow I need to attach a custom IReplyChannel into that.

     

    Again, thanks for the pointers and I'll keep plugging away.

     

    -Carole

     

    Monday, April 28, 2008 6:50 PM
  • I suggest you take a look at the documentation for building a custom channel: http://msdn2.microsoft.com/en-us/library/ms788753.aspx

    You'll need a channel factory and a binding element to plug into a customBinding, or your own WsDualHttpWithFaultConverterBinding :-)

    Justin Smith's "Inside WCF" has a good walkthrough of building custom channels, binding elements and bindings.
    Monday, April 28, 2008 6:56 PM
  • On the client side, you could also attach a custom IClientMessageInspector to the proxy to handle converting the FaultExceptions back into a more consumable .Net Exception. You'd implement the AfterReceiveReply method to do the conversion. I'm guessing this is easier than implementing a custom channel.
     
     
    Monday, April 28, 2008 7:12 PM
  • For completeness, I need to add that you'd also need to implement a custom IEndpointBehavior. It works like this:
     
     - Attach the custom message inspector mentioned in my previous post to the custom IEndpointBehavior in the ApplyClientBehavior method.
    Code Snippet

            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                // Add the custom message inspector
                clientRuntime.MessageInspectors.Add(new CustomMessageInspector());
            }

     

     - Add the endpoint behavior to the proxy:
    Code Snippet
    // attach the message inspector before opening
    proxy.ChannelFactory.Endpoint.Behaviors.Add(new CustomMessageInspectorEndpointBehavior());

     

     

    Monday, April 28, 2008 7:29 PM
  • After several days of working through implementing a FaultConverter (which required implementing custom channels, bindings, binding elements, and a channel factory), I finally got a working solution.  And then I saw the recommendation to use the IClientMessageInspector.  In about an hour, I had another working solution. 

     

    I just have one question about using that.  The whole point of the exercise is for the client to receive a standard exception and not a FaultException.  Would I be causing problems by throwing an exception in AfterReceiveReply?  I don't want to be short-circuiting any logic in the channel stack by throwing it there.  Implementing the FaultConverter, at least, allows WCF to behave normally.

     

    Thanks,

    Carole

     

    Tuesday, April 29, 2008 8:08 PM
  • I was unable to find a definitive resource on the web that says "no, you shouldn't be throwing exceptions from your implementation of IClientMessageInspector".  However, after looking at the code with Reflector, it does seem that if your exception propagates from AfterReceiveReply, then there is some logic in the client runtime that is not executed.  For example, at least as far as I could tell, parameter inspectors won't be invoked if the message inspector throws.  Additionally, I think that the validation logic that ensures all headers marked with MustUnderstand are indeed understood will not take place.

    The FaultConverter approach (albeit more difficult) is the documented way of translating faults to exceptions.  I think that since you already did the hard work, you might find it more reliable to stick to that approach.
    Tuesday, April 29, 2008 8:38 PM
  • I finally got an answer from a developer at Microsoft and he assured me that all critical processing would already have been done by AfterReceiveReply in the IClientMessageInspector.  So throwing an exception here would be fine.  Using a FaultConverter is more elegant as it works within the WCF processing, but the overhead necessary to simply implement a FaultConverter makes it not as useful as the IClientMessageInspector.  So that is what we're going with.  Thanks everyone for their help!

     

    Tuesday, May 20, 2008 12:52 PM