.net – Custom Exception as Detail in Fault Exception

exception handlingfaultexceptionnetwcf

I'm trying to throw my own custom exception inside a FaultException from my WCF service and catch it in my WCF client. On the client side, however, the exception is caught as a non-generic FaultException and the details of my custom exception are lost.

My custom exception is:

[Serializable] public class MyCustomException : ApplicationException 
{ ... }

Here's how I throw it:

throw new FaultException<MyCustomException>(new MyCustomException("foo bar!"));

(Note that I do have a [FaultContract(typeof(MyCustomException))] placed over my method in the interface)

And here's how I try to catch it in my client:

...
catch (FaultException<MyCustomException> mcex)
{
    Console.WriteLine(mcex); 
}
 catch (FaultException fex) 
{
    Console.WriteLine(fex); 
}

My goal is for the exception to be caught in the first catch clause above, but it ends up caught in the second catch clause.

The curious thing is that if I replace MyCustomException with ApplicationException then indeed FaultException is properly caught.

I'm guessing the problem is that MyCustomException is serialized a Serializable (and not via the DataContractSerializer) and that maybe I'm missing some additional directive to WCF. Something in the line of a ServiceKnownType attribute? (Though I tried that, to no avail).

Best Answer

Yes, you won't be able to catch the generic FaultException until you specify that type as a fault contract in your service contract:

[ServiceContract]
interface IYourService
{
   [OperationContract]
   [FaultContract(typeof(MyCustomException))]
   SomeReturnValue YourMethodCall(SomeInputValue input);
}

Only once you do this, then you can catch and handle the specific, generically typed FaultException in your client side code.

See the MSDN docs on FaultException<T> this blog post for some more background and good info on WCF error handling.

Also, I would personally always decorate my fault contract classes with a [DataContract] attribute (and all the members I want to have serialized with [DataMember]):

[Serializable] 
[DataContract]
public class MyCustomException : ApplicationException 
{ ... }