24 June, 2008

WCF and Custom Exception Handling (custom exceptions), part 1

As this seems a rather popular topic, I’ve decided to rewrite this post in a more “reader friendly” format. Here goes…


I was really under the impression that WCF allowed "any" type to be used as FaultContract<T>, as long as the type was marked with the [Serializable]-attribute. Surprise-surprise - that is not the case!


If you do not want to declare a completely custom type using the [DataContract] attribute on your own class, but instead provide an Exception-derived type (which is quite common in .NET-.NET scenarios where no interoperability is required), you need to take into account a couple of things. In addition - the "exception based" programming model is more in sync with the general .NET paradigm and thereby easier to handle by a programmer.


First of all - the type to be used as <T> in the FaultContract<T>, is to inherit from CommunicationException (not System.Exception); or so the documentation says. In reality System.Exception will actually do, but better to stay current with the documentation. Next is the really important part - Provide a protected constructor allowing for the serialization process taking SerializationInfo and StreamingContext as arguments:

[Serializable]
public class MyCustomException : CommunicationException
{
public MyCustomException()
{ }

public MyCustomException(string msg) : base(msg)
{}

protected MyCustomException(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)
{}
}
SERVICE: When declaring a type like the above, it will be (re)thrown at the Client-side (by the proxy) correctly when declared in the ServiceContract like this using the FaultContract(type) as seen below:
/// <summary>
///
My service contract
/// </summary>
[ServiceContract(Namespace="UniqueString")]
public interface IMyService
{
/// <summary>
///
Prints the string.
/// </summary>
/// <param name="msg">
The MSG.</param>
[OperationContract]
[FaultContract(typeof(MyCustomException))]
void PrintString(string msg);
}

The service implementation throwing the exception (MyCustomException) looks like this:

public class MyService : IMyService
{
#region IMyService Members

public void PrintString(string msg)
{
if (string.IsNullOrEmpty(msg))
throw new FaultException<MyCustomException>(new MyCustomException("Input was null"));

//to stuff with input, otherwise...
}

#endregion
}

CLIENT: Throwing this exception-derived type in the service implementation will propagate to the Client just fine and can be caught like this in the client:

    void CallService()
{
try
{
proxy.PrintString(null);
}
catch (FaultException<MyCustomException>)
{
Console.WriteLine("The proper exception caught");
}
catch (CommunicationException)
{
Console.WriteLine("The INCORRECT exception caught");
}
}
}
2011.03.16: Update: To be able to convey your own custom data as well, see this post:
http://blog.clauskonrad.net/2011/03/how-to-wcf-and-custom-exception.html
Technorati Tags:

8 comments:

Anonymous said...

Thank you for the post, Claus; it helps.

Anonymous said...

Thank you so much for this very helpful and understandable post.

Anonymous said...

Thanks a lot man. It helped me.

Anonymous said...

thank you for the post, it helps a lot!
btw, if you inherit from Exception, it doesn't work. I have to say that i didn't implemented the protected constructor, but it didn't worked until the custom exception inherits from communicationException.

Anonymous said...

Perfect, thank you. Saved me a lot of time!

Blanes said...

Great post..I still have a problem. MyCustomException have a property named IDUser..after this exception is thrown in client, this property is reinitialized(with 0). How can I bring more info to the client(more than an Exception have)?

Erkan Aslanel said...

you are hero.i created CustomException:Exception without third constructor.I only catched exception in fault exception (didn't catch FaultException).I gonna crazy about that.So third constructor solve that.Thank you God Bless you.

us essay writing service said...

These types of things are supposed to be handled by the professionals which are having better experience about such things. There are many new summaries that are meant to be seen infinitely.

iPhone/XCode - not all cases are equal!

This bit me! Having made some changes to an iPhone application (Obj-C); everything worked fine in the simulator. But, when deploying the s...