Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

A Beginner's Tutorial for Understanding Exception Handling, FaultExceptions and FaultContracts in WCF

4.88/5 (26 votes)
1 Mar 2013CPOL6 min read 84.2K   1K  
This article discusses about exception handling in WCF services, FaultExceptions and introduces the FaultContract.

Introduction

In this article we will discuss how to perform exception handling in WCF services so that the clients can get the information about the exceptions and take some actions for rectification. We will see how we can pass the exception information to the WCF clients.

Background 

In a normal .Net application handling exceptions is pretty straight forward using the try catch blocks. The aspect about notifying the user is also very straight forward as in we can simply display the error message to the user from after handling the exception. Based on this the user of our application can take corrective actions.

From a WCF service perspective, all the normal exceptions inside the WCF service can still be handled in the similar manner as if they are normal .NET exceptions. In fact they are normal .NET exceptions. The major challenge for a service is to propagate the exception information to the user. The reason for this is that the user of the service will most probably be consuming the service in form of document and soap messages and secondly because the the consumer of the service could be in some other technology and sending him .NET specific exception doesn't make any sense.

Sending the exception information to the user is never a good idea. So when I say sending the exception information to the user, the user is in fact the application/developers which is trying to consume the service and not the end user. End user should always meet with user friendly messages and never with the exceptions. The consuming application developers, on the other hand, need to know the details of the application so that they can understand what is going wrong and what corrective actions should be taken.

In a service based application scenario when the applications are talking in terms of documents i.e. soap messages the error and exception reporting from the service to the service consumer also happen in the form of soap elements. SOAP faults are the way to propagate the exceptions from the service to the client application.

Does this mean the service developers will have to create the SOAP's fault manually whenever any exception is met. The answer to that is no. WCF services provide a very nice abstraction over these in form of FaultException and the services can easily propagate the exception information to the client using the FaultException and FaultContract.

Using the code

Let us now see how in the absence of FaultExceptions it is not possible to get the exception details. Also let us try to see how we can use FaultContracts and FaultExceptions to communicate better with the client applications in exceptional scenarios.

Creating a Simple Service

Let us start by creating a sample service with two methods. One for multiplication of 2 numbers and other for dividing the two numbers. In the multiplication method we will throw a custom exception if any of the number is 0. In the division function the framework will throw a DivideByZeroException. We will try to propagate these two exceptions to the clients.

Note: This article assumes that the reader at least knows how to create and consume a simple WCF service. If that is not the case please refer to the following article before reading this further: A Beginner's Tutorial for Understanding Windows Communication Foundation (WCF)[^]

Service contract of the sample service will look like

C#
[ServiceContract]
public interface ITestService
{
    [OperationContract]
    int Multiply(int num1, int num2);

    [OperationContract]
    int Divide(int num1, int num2);
}

The service implementation of the service will look like

C#
public class TestServiceImplementation : ITestService
{
    public int Multiply(int num1, int num2)
    {
        if (num1 == 0 || num2 == 0)
        {
            throw new Exception("Please pass only non zero numbers");
        }

        return num1 * num2;
    }

    public int Divide(int num1, int num2)
    {
        try
        {
            return num1 / num2;
        }
        catch (DivideByZeroException ex)
        {
            throw ex;
        }
    }
}

Creating the Service Client

As for the client, Let us create a simple console client. First let us try to pass non zero values to the service.

C#
using (ServiceReference1.TestServiceClient client = new ServiceReference1.TestServiceClient())
{
    int num1 = 6;
    int num2 = 3;

    int resultMulitply = client.Multiply(num1, num2);
    int resultDivide = client.Divide(num1, num2);

    Console.WriteLine("Multiplication: {0}, Division: {1}", resultMulitply, resultDivide);
}
Image 1

Simple Exception Handling

Let us not try to pass the second argument in the multiply function as 0. We will get an exception with message as:

Unhandled Exception: System.ServiceModel.FaultException: The server was unable to
process the request due to an internal error.
Same will be the case if we pass the second argument in the divide function as 0.

Image 2

Now since we got the exception, we know something went wrong. But the exception we received was not very useful. To get some useful information from the exceptions we need to propagate the cause of exception to the client application. This is exactly where the FaultException comes in picture.

Handling FaultExceptions

Let us now use a simple FaultException and throw it out of our service's Divide method.

C#
public int Divide(int num1, int num2)
{
    try
    {
        return num1 / num2;
    }
    catch (DivideByZeroException ex)
    {
        throw new FaultException(ex.Message);
    }
}

This will take care of creating the fault element in the SOAP message and let the client application know about the detailed exception. The client application will now have to catch all the

FaultExceptions
coming from the service.

C#
try
{
    using (ServiceReference1.TestServiceClient client = new ServiceReference1.TestServiceClient())
    {
        int num1 = 6;
        int num2 = 3;

        int resultMulitply = client.Multiply(num1, num2);
        int resultDivide = client.Divide(num1, 0);

        Console.WriteLine("Multiplication: {0}, Division: {1}", resultMulitply, resultDivide);
    }

    Console.ReadLine();
}
catch (FaultException ex)
{
    Console.WriteLine(ex.Message);
}

Now when we try to call the Divide function with second argument as 0 we will not only get the exception but will also get the detailed reason for the exception.

Image 3

FaultContract and Strongly typed FaultExceptions

So using the fault exception made it possible for the services to propagate the exception messages to the client. Now what if we need to create our own types in the service to categorize and provide much more detailed information about the exception. More information than a simple string message.

WCF services also provides a way for us to throw custom objects in our fault exceptions. These custom objects will contain the detailed information about the exception. These objects will have to be exposed as the

FaultContract
from the service.

Let us now try to create a simple object called MyExceptionContainer which will contain the detailed information about the exception(based on application requirements).

C#
[DataContract]
public class MyExceptionContainer
{
    [DataMember]
    public string Messsage { get; set;}
    [DataMember]
    public string Description { get; set; }
}

We will expose this as a fault contract for the Multiply function.

C#
[OperationContract]
[FaultContract(typeof(MyExceptionContainer))]
int Multiply(int num1, int num2);

Now this Mulitply function's implementation needs to be changed to throw this FaultContract object in the exception. Let us see how that can be done.

C#
public int Multiply(int num1, int num2)
{
    if (num1 == 0 || num2 == 0)
    {
        MyExceptionContainer exceptionDetails = new MyExceptionContainer();
        exceptionDetails.Messsage = "Business Rule violatuion";
        exceptionDetails.Description = "The numbers should be non zero to perform this operation";
        throw new FaultException<MyExceptionContainer>(exceptionDetails);                
    }

    return num1 * num2;
}

Now this strongly typed FaultException will propagate this exception to the client. let us see how we can handle this in out client application.

C#
try
{
    using (ServiceReference1.TestServiceClient client = new ServiceReference1.TestServiceClient())
    {
        int num1 = 6;
        int num2 = 3;
        int resultMulitply = client.Multiply(num1, 0);
        int resultDivide = client.Divide(num1, num2);

        Console.WriteLine("Multiplication: {0}, Division: {1}", resultMulitply, resultDivide);
    }

    Console.ReadLine();
}
catch (FaultException<ServiceReference1.MyExceptionContainer> ex)
{
    Console.WriteLine(ex.Detail.Messsage);
    Console.WriteLine(ex.Detail.Description);
}
catch (FaultException ex)
{
    Console.WriteLine(ex.Message);
}

Now when the multiply function will be called with any argument as 0 then the strongly typed exception will be thrown and the client application can handle it using FaultException<T> type of exception.

Image 4

Now we have a sample application which is capable of sending the exceptional messages to the client application. It is always a good idea to have proper FaultContracts and pass on them to the client applications because sending the simple faults can be sometime not very helpful for the client application.

Point of interest

In this article, we saw how we can perform exception handling inside the WCF service using normal .NET exception handling techniques. We also saw how we can propagate proper messages and data to the client applications in case of exceptions. This article is written from a beginners perspective and thus it only talks about the FaultExceptions and FaultContracts. There are few very good patterns and practices that people follow to specify FaultContracts and throwing FaultExceptions. Those were not covered in this article. I hope this has been informative.

History

  • 02 March 2013: First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)