0

I'm trying to create a robust way to pass exceptions from the server to the client but I seem to be missing something.

The intention is to use FaultException to wrap actual serializable Exception subclasses caught on the server side, pass them over WCF, then rethrow them at the client side.

Server side code:

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

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

Client side code:

try
{
    client.Foo();
}
catch (FaultException<MyException> ex)
{
    throw ex.Detail;
}
catch (FaultException ex)
{
    throw;
}

MyException:

[Serializable]
public sealed class MyException: Exception
{
    public MyException(string description)
        : base(description)
    {
    }

    public MyException()
    {
    }

    public MyException(string message, Exception innerException) 
        : base(message, innerException)
    {
    }

    private MyException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}

What I'm observing is that the server side code executes the catch (MyException ex) block but when the fault gets back to the client side, the code goes into the catch (FaultException ex) block and rethrows a normal FaultException, rather than MyException (interestingly, the FaultException does contain the message of the original MyException object).

Note that both the client and server have visibility of MyException, svcutil generates the correct attributes for the client side service contract and the WCF logs don't show any serialization errors.

Tudor
  • 61,523
  • 12
  • 102
  • 142
  • What happens if you put a `catch(MyException ex)` on the client side? Also can you show the code for `MyException`? – Scott Chamberlain Jul 21 '15 at 15:19
  • @Scott Chamberlain: catching `MyException` didn't change anything, the actual type caught by the client code is untyped `FaultException`. Code for `MyException` posted. – Tudor Jul 21 '15 at 15:32
  • Try the [Generic variation](https://msdn.microsoft.com/en-us/library/ms576199(v=vs.110).aspx) of FaultException. It lets you set some detail object. But you'd still be catching a FaultException. – musaul Jul 21 '15 at 16:08
  • @musaul: Unless I'm missing something, that's exactly what I'm doing in the code posted? – Tudor Jul 21 '15 at 16:15
  • Possible duplicate of http://stackoverflow.com/questions/5717231/faultexception-and-custom-exception-wcf But I don't want to vote to close because I have single vote close power on C# tagged questions and I am not confident enough to be the only person who says this is a duplicate. (In summary of the duplicate, even though your exception is marked Seriaizeable you still need a `DataContract` attribute on it) – Scott Chamberlain Jul 21 '15 at 16:16
  • @Scott Chamberlain: Ugh, that seems to be the case here as well. Problem is, as someone else commented there, marking `MyException` as both `[Serializable]` and `[DataContract]` produces a compilation error. – Tudor Jul 21 '15 at 16:19
  • @Scott Chamberlain: Also, I'd understand the need for `[DataContract]` if `MyException` was only known to the server side, but in my case both the client and the server build against and assembly that contains the exception. – Tudor Jul 21 '15 at 16:35

0 Answers0