7

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.

Tudor
  • 61,523
  • 12
  • 102
  • 142
  • Could it be because you throw new FaultException(ex, ex.Message); and not "throw new FaultException(ex, ex.Message);" ? Also, the TDetail of FaultException should not necessary be an exception – hazzik Jun 30 '15 at 13:29
  • @hazzik: I'm putting the actual exception in the Detail because I want to rethrow it on the client side. – Tudor Jun 30 '15 at 13:32

2 Answers2

3

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.

Ricardo Pontual
  • 3,749
  • 3
  • 28
  • 43
  • Thank you, this worked. Sadly, it seems I have to have explicit `throw` statements for each and every type that inherits from my superclass of exception. – Tudor Jun 30 '15 at 20:58
0

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.

GinjaNinja
  • 776
  • 6
  • 18
  • If you read the OP's post they have already tried implementing FaultException. The article you have linked to is about how to implement FaultException. Even as a comment, this does not help the OP. If you have a suggestion as to how they should change their code please post it. I'm sorry to be harsh, and I know you're trying to be helpful but this is not a good answer. – tom redfern Jun 30 '15 at 16:11
  • Additionally you do not recall correctly. Throwing a FaultException and letting it bubble back to the caller is *exactly* how you *should* do it. Then the caller can catch and handle the exception naturally in their calling code. – tom redfern Jun 30 '15 at 16:14
  • @Tom Redfern, I think this is a little harsh. The accepted answer throws back a fault exception with a type of the users making. This type is not inherited from Exception and hence is not an Exception as such. This is exactly what the article posted suggests. Also, I did not suggest that the user should not through a FaultException, purely that passing pack the full Exception detail may not be a good idea. – GinjaNinja Jul 01 '15 at 08:48
  • Apologies - perhaps this was harsh. I assumed that by *you cannot actually pass the exception itself back to the client*, you were asserting that passing a FaultException back to the client was incorrect. I now see this was not your aim. However, I do still think your answer unhelpful as it stands, because rather than post a solution you linked to an article containing a solution without quoting the relevant bits (see http://stackoverflow.com/help/how-to-answer for what to do when linking). If you make an edit to your answer I will remove the downvote (voting locked for me until you do). – tom redfern Jul 01 '15 at 09:08