It is quite common to use try/catch blocks in our methods and display a user-friendly message in the UI. The actual technical error is never displayed to the front-end user. But consider the case of service-oriented applications, that act as an API and provide services to the clients. If any error occurs at the service end, we can simply catch the exception and perform the required action. But what about the client? The client that uses this service will receive a long exception message, of which he has no idea about. Also, a good application should never display error messages at the front end. WCF provides a way of handling these situations, by the use of a Fault Contract.
So let's try to understand some basics of this concept.
What is Fault Exception?
For this, we will create 2 applications. One will be our WCF service named Demo and another is a WCF client, that will consume this service. Our service will be exposing an operation to client (named DivideNumber), to divide a number by zero. This is intentionally done to raise an exception in the service operation. We will not add any try-catch block in either of the applications. So when our service is ready, then add its reference to the client application and invoke the service method DivideNumber. Now run the application and see what happens.
A big bang and the yellow screen will appear. But this will not provide any idea to us, about what happened in the service. So we will do what it suggests. We go to our service web.config and navigate to the serviceBehaviors section and change the setting includeExceptionDetailInFaults to true.
Setting this property to true allows the actual exception details to be sent to the client, consuming the service. Now, update the service reference in the client application and run the application again and we can see what was the actual exception and resolve it.
The error message that is transferred in both the cases above, is passed through the <faultstring> tag in the response SOAP XML. We can test this through the WCF Test client. Run the service test client, invoke the method and we can see the exception string in the XML generated for the SOAP response.
Case 1: includes where we have not passed the details of the exception.
Case 2: is where we have passed the actual exception to the client, by setting includeExceptionDetailInFaults to true, in service web.config.
But this kind of process should be only followed for the development environment and never in a production environment. The reason is that a service-oriented application should never expose information about what exactly is happening behind the scenes. Exposing any exception like this can expose the logic you are using in your application, to the client. Also, displaying the exceptions to the client is never a good thing.
Although its not a good thing to send the error information to the client, but the client should still also get to know whether the operation he called for has succeeded or not. But the point is, if our service is being used by various languages like PHP, Java and so on, then passing the actual .NET based exceptions to the client, is also not feasible or advisable. So here the FaultException class is used. The fault exception is used to pass the custom error message from the server to the client, inside the SOAP response XML. When the response is received by the client, the custom exception message is set by the service and is also available in the <fault> tag in the SOAP.
In order to do this, the service needs to throw a new instance of the FaultException class, with the custom message set in its constructor. Let's say, we pass the custom message "Service was unable to divide by zero" in the constructor.
Now run the test client and see the response XML. The custom message that we have added, will be now carried to the client, by the <fault> tag.
It is more like adding a try-catch to the entire communication between the client and the service. An exception is caught at the service level and is propagated to the client using a throw, via SOAP message. The client catches the exception and gets the exception details.
Now, update the service reference in the client application and run it again. It will display the message set by the service. Even if we keep the setting includeExceptionDetailInFaults in web.config to true or false, it will still display the message from the FaultException class, that the service has added. So the client will never be informed of how your service is exactly working, but will still be informed of the status of his request.
Fault Contract and strongly typed FaultExceptions
Now that we have a way to send exceptions to the client, wouldn't it be great if we could send extra information related to the exception, apart from the custom exception message or send strongly typed exceptions, with selected information? The good news is that it is possible. WCF provides a FaultContract attribute to achieve this requirement. This attribute provides the ability to create strongly-typed fault exceptions, or in other words, we can create various custom classes to represent various types of exceptions that we can have in our application and allow them to propagate to the client application.
To do so, we will add a new class to represent our exception type and 3 properties to it, that will represent the entire exception to the client. Our class will be named ExceptionFaultContract and the properties will be StatusCode, a user defined message and its description. Next, we need to add DataContract and DataMember attributes to this class.
To pass this class as a strongly typed FaultException for this method, we need to add the FaultContract attribute on our method and specify its type using typeof expression. It is like a List<String> representing a generic List of string type, setting the typeof property that represents the FaultException of the type ExceptionFaultContract. This is what is meant by strongly-typed FaultException.
It is mandatory to provide the typeof property with FaultContract. Also, if no fault contract attribute is applied, the default exception that will be returned by WCF will be of type FaultException.
Our method implementation will now also change slightly to catch the exception and return the custom fault exception in the form of ExceptionFaultContract. For strongly typed fault exceptions, the FaultException class uses FaultException<TDetail>, where TDetail represents the custom type. Compare this with the example of List<string> that we discussed above. So our code becomes like:
Run the WCF test client and invoke the method. We can see the details of the custom message that we set.
Now in the client application, we will catch the exception using the reference of this exception type defined in the service. Run the application and see the exception. This exception fault will be accessible through the Detail property of the FaultException instance.
So we can see the details of the exception, that we had set in the service.
Why use FaultExceptions?
This type of solution is very helpful in situations where the client and server are of different platforms. For example, you might have client applications in Java or PHP. So, if there is any .NET specific exception in the service, we can't send the fault exception to the client directly, since client will not understand .NET based exceptions. They only need to know that an exception has occurred and if possible, a reason for it. So it becomes very important to use FaultExceptions normally only or use the strongly-typed fault exceptions.
So this was all about the basic concepts of WCF fault exceptions and fault contracts. I hope you enjoyed reading it