In an XML Web Service and WCF service, the server side will return any unhandled exception as SoapFault
in the returned message. For WCF service operations, exceptions are returned to the client through two steps:
- Map exception conditions to custom SOAP faults
- Services and client send and receive SOAP faults as exceptions
By default, WCF will return the simple error message or complete exception information (including Callstack) as the Fault content. However, sometimes we want to encapsulate the raw exception information or return some user-friendly error to the client side. To support this kind of customized exception-information format, WCF has provided the FaultContract
and FaultException
features. FaultException
is a new exception type that uses Generic to help WCF service encapsulate various kinds of custom error data objects in a unified way. FaultContract
is used to formally specify the type of FaultException
that will be returned from the target WCF service operation, so that the client consumers can properly handle and parse it.
- First, create the custom error type that will be returned to the service client as exception information. The custom error type is defined as a standard
DataContract
type. - Then, apply the custom error type to the service operation (which will return this custom error type) through a FaultContractAttribute.
- The following code shows a sample custom error type and the service operation that applies it:
[DataContract] public class UserFriendlyError { [DataMember] public string Message { get;set; } } [ServiceContract] public interface ICalcService { [OperationContract] int Divide(int lv, int rv); [OperationContract] [FaultContract(typeof(UserFriendlyError))] int DivideWithCustomException(int lv, int rv); }
- Finally, we need to add our exception handling code in the service operation's implementation and return the custom error type through the
FaultException<T>
type (seeDivideWithCustomException
method shown as follows):public int Divide(int lv, int rv) { if (rv == 0) throw new Exception("Divided by Zero is not allowed!"); return lv / rv; } public int DivideWithCustomException(int lv, int rv) { if (rv == 0) throw new FaultException<UserFriendlyError>(new UserFriendlyError() { Message = "Divided by Zero is not allowed!" } ); return lv / rv; }
The FaultContractAttribute
applied on the service operation will make the runtime generate corresponding metadata entries in the WSDL document (as shown in the next screenshot). Thus, the generated client proxy knows how to handle this custom error type.

When invoking the operation, we can add code to handle the specific FaultException
and get user-friendly error information from the Exception.Detail
property.
try
{
//call the operation with invalid parameter
}
catch (FaultException<UserFriendlyError> fex)
{
Console.WriteLine("Error: {0}", fex.Detail.Message);
}
If we use Fiddler or message logging to inspect the underlying SOAP message, we can also find the custom error data in XML-serialized format:

Since the custom error type used by FaultContract
supports any valid DataContract
type, we can define various kinds of custom exception data content (from simple primitive types to complex nested classes).
- Generating DataContract from XML Schema
- Capturing a WCF request/response message via Fiddler tool in Chapter 12
- Complete source code for this recipe can be found in the
\Chapter 1\recipe7\
folder