locked
Generic exception handling strategy RRS feed

  • Question

  • Hi,

    What is the recommended approach for exception handling on the WCF tier? The SDK and some of the threads on this forum are stating that separate data contracts should be created to represent the various SOAP faults.  Then, I am supposed to mark up the OperationContract methods with the "expected" faults (by the way, the documentation says that I can mark a service contract itself with a list of expected faults, but the compiler is claiming that it's only available for methods -- is the documentation out of date?).  Then, in my service operation, I am supposed to wrap my calls (to business logic layer, let's say) in a try/catch block and provide mapping between specific exceptions and SOAP faults in the relevant "catch" blocks.

    However, I am trying to come up with a more generic solution so that developers don't have to write the try/catch block in every single service method and perform the exception-fault mapping.  In a "normal" .NET app I would wire up to the UnhandledException/ThreadException (for WinForms/Console/NT Service) or Application_Error(in case of ASP.NET) and use a policy (Enterprise Library) for handling the exceptions.  The exception would either be rewrapped, replaced, and/or logged.

    WCF's IErrorHandler interface seems like it provides the appropriate hook, but I am more curious about the recommended approach for an SOA system.  In the ProvideFault method, I'd need to inspect the incoming Exception and based on some policy (can't really use EntLib here), convert the exception to the appropriate SOAP fault.  I was thinking of creating a simple fault that contains a string property that represents the message of the error, and then an enum that describes the type of error (i.e. DbConcurrency, DbDeadlock, etc) so that the client can (potentially) provide different handling on their end.  I could also use some policy that would tell me whether I can take the real exception's message as-is and stick into the fault, or shield it with a different message.

    Does this sound correct? What's the appropriate balance between providing a semantically strong contract and some flexibility?

    Thanks

    Monday, September 25, 2006 9:52 PM

Answers

  • I think everything you say sounds good.  In particular, IErrorHandler is a 'centralized' place you can do the exception->fault mapping if you expect many different operations to throw various kinds of exceptions and all of them to have the same mapping. 

    (Yes, we used to allow [FaultContract] on the interface, but now it only is supported on operations, so the docs you have are out of date.)

    Note that even when you don't put a [FaultContract] attribute on an operation, you can always throw a FaultException from a method to return a 'generic' fault back to the client.  As you say, choosing between always doing FaultException<OneFixedType> where the fixed-type has an error code, and FaultException<Foo>/FaultException<Bar>/etc just changes the 'shape' of the catch handlers on the client.

     

    Tuesday, October 17, 2006 8:25 AM

All replies

  • I suppose the other option is to create a separate fault rather than using an error code in the single fault.  The benefit of this is that the client can use structured exception handling, but now I have a potential explosion of fault types that are all structurally equal but are different types.

    Anyhow, would love to hear some opinions from the folks on here.

    Thanks,

    Vitaly

    Tuesday, September 26, 2006 12:53 AM
  • So what do the folks here think about this? I realize that my initial post was rather wordy, but I'd love to hear feedback.

    Thanks

    Wednesday, September 27, 2006 12:33 AM
  • I think everything you say sounds good.  In particular, IErrorHandler is a 'centralized' place you can do the exception->fault mapping if you expect many different operations to throw various kinds of exceptions and all of them to have the same mapping. 

    (Yes, we used to allow [FaultContract] on the interface, but now it only is supported on operations, so the docs you have are out of date.)

    Note that even when you don't put a [FaultContract] attribute on an operation, you can always throw a FaultException from a method to return a 'generic' fault back to the client.  As you say, choosing between always doing FaultException<OneFixedType> where the fixed-type has an error code, and FaultException<Foo>/FaultException<Bar>/etc just changes the 'shape' of the catch handlers on the client.

     

    Tuesday, October 17, 2006 8:25 AM