7
votes

I'm trying to send exceptions over WCF in the most generic way possible. Here's what I've got:

[ServiceContract]
interface IContract
{
    [OperationContract]
    void Foo();
}

class ContractImplementation: IContract
{
    public void Foo()
    {
        try
        {
            Bar();
        }
        catch (Exception ex)
        {
            throw new FaultException<Exception>(ex, ex.Message);
        }
    }
}

The exception that is actually coming out of Bar is:

[Serializable]
class MyException : Exception
{
    // serialization constructors
}

The error I'm seeing in the server-side WCF logging is:

Type 'MyException' with data contract name 'MyException:http://schemas.datacontract.org/2004/07/MyException' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

What I've tried so far:

[ServiceKnownType(typeof(MyException))]
[ServiceContract]
interface IContract
{
    [FaultContract(typeof(MyException))]
    [OperationContract]
    void Foo();
}

But no luck.

2
Could it be because you throw new FaultException<Exception>(ex, ex.Message); and not "throw new FaultException<MyException>(ex, ex.Message);" ? Also, the TDetail of FaultException should not necessary be an exception - hazzik
@hazzik: I'm putting the actual exception in the Detail because I want to rethrow it on the client side. - Tudor

2 Answers

3
votes

First, in MyException, remove the inheritance from Exception and make it public.

Second, when you declare your service contract, declare exception as it follows:

[FaultContractAttribute(
        typeof(MyException),
        Action = "", 
        Name = "MyException", 
        Namespace = "YourNamespace")]
    [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
    [OperationContract]
    void Foo()

Finally, you can throw your Exception like this:

throw new FaultException<MyException>
             (
                 new MyException(ex.Message),
                 new FaultReason("Description of your Fault")

             );

Hope it helps.

0
votes

Firstly - apologies, I would rather post this as a comment and not as an answer. As a relative noob, I am unable to!

This article discusses in a decent level of detail how to relay exception details back: http://www.codeproject.com/Articles/799258/WCF-Exception-FaultException-FaultContract

Afaik, you cannot actually pass the exception itself back to the client as an exception is not SOAP compliant. Also consider whether passing the whole exception could compromise the security of your code.