.Net WFC/Web service exception handling design pattern

exceptionnetwcfweb services

I'm trying to come up with a simple, easy to use design pattern for error handling in a .net wcf service (specifically a silverlight enabled wcf service). If an exception gets thrown in the service method the silverlight application will see a CommunicationException stating "The remote server returned an error: NotFound —> " and possibly a stack trace depending in your settings, which is entirely not useful because it doesn't tell you the actual error, and usually the real error is not "NotFound".

Reading up on web services and wcf services and exceptions, You need to throw soap/wcf standard exceptions such as FaultException or SoapException. So for a wcf service you need to wrap each method in a try catch, catch each exception, wrap it in a FaultException and throw it. At least that is my understanding, correct me if I am wrong.

So I've created my design pattern:

[ServiceContract(Namespace = "http://MyTest")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DataAccess
{
    /// <summary>
    /// Error class, handle converting an exception into a FaultException
    /// </summary>
    [DataContractAttribute]
    public class Error
    {
        private string strMessage_m;
        private string strStackTrace_m;

        public Error(Exception ex)
        {
            this.strMessage_m = ex.Message;
            this.strStackTrace_m = ex.StackTrace;
        }

        [DataMemberAttribute]
        public string Message
        {
            get { return this.strMessage_m; }
            set { this.strMessage_m = value; }
        }

        [DataMemberAttribute]
        public string StackTrace
        {
            get { return this.strStackTrace_m; }
            set { this.strStackTrace_m = value; }
        }

        //Convert an exception into a FaultException
        public static void Throw(Exception ex)
        {
            if (ex is FaultException)
            {
                throw ex;
            }
            else
            {
                throw new FaultException<Error>(new Error(ex));
            }
        }
    }

    [OperationContract]
    [FaultContract(typeof(Error))]
    public void TestException()
    {
        try
        {
            throw new Exception("test");
        }
        catch (Exception ex)
        {
            Error.Throw(ex);
        }
    }
}

So to make a long story short, I'm still not getting the correct error in my silverlight application. I inspect the AsyncCompletedEventArgs.Error object and it still contains a CommunicationException object with the generic error. Help me come up with a nice simple design pattern to allow me to easily throw the correct exception from the service, and easily catch it in the application.

Best Answer

I would suggest you to centralize the error handling of your WCF service instead of putting try/catch on every method. To do this you can implement the IErrorHandler interface:

public class ErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        return true;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
    {
        DataAccessFaultContract dafc = new DataAccessFaultContract(error.Message);
        var fe = new FaultException<DataAccessFaultContract>(dafc);
        Message fault = fe.CreateMessageFault();
        string ns = "http://www.example.com/services/FaultContracts/DataAccessFault";
        msg = Message.CreateMessage(version, fault, ns);
    }
}

The ProvideFault method is called whenever one of your OperationContract throws an exception. It will convert the exception into a custom defined FaultContract and send it to the client. This way you no longer need to put try/catch in every method. You can also send a different FaultContract depending on the exception thrown.

On the client side you need to catch FaultException<DataAccessFaultContract> every time you call a method on your web service.

Related Topic