How to: Return Custom Error Messages Using FaultContracts

Retired Content

The Web Service Software Factory is now maintained by the community and can be found on the Service Factory site.

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies.
This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Retired: November 2011

When interacting with WCF services, client applications rely on information from the Web Service Description Language (WSDL) associated with a service to determine data contracts and operations supported by the service. It is possible to return exception information without defining exception data contracts, but the preferred approach is to define all the different exceptions that a service can return. In WCF, these exceptions are referred to as faults, which is the term that is used throughout the remainder of this topic. Along with defining the fault types that can be returned, WCF services should always use custom fault types instead of internal .NET Framework types, such as managed exceptions.

To support the use of custom faults, WCF services use the FaultContractAttribute to formally specify faults that can be returned from a service operation. Types specified in a FaultContractAttribute must be serializable as DataContract,SerializableAttribute, or ISerializable. When a FaultException<T> is thrown using a custom fault defined in FaultContract, client applications can also catch these specific faults using the FaultException<T> generic type.

The Web Service Software Factory provides a way to create fault contracts. For more information about the creation of fault contracts, see Exercise 2: Modeling the Data Contracts in the Building a Web Service Hands-on Lab on CodePlex.

Process

This process assumes that you have created a WCF service using the Web Service Software Factory.

To return custom errors in a FaultContract

  1. In the operation of the service implementation, create an instance of the fault contract and initialize it with information that should be returned to the client application.
  2. Throw a new FaultException<T> using the FaultContract for generic type T.

The following code example shows FaultContract type named InvalidNameFault that is initialized and then thrown using the FaultException<T> generic type.

InvalidNameFault fault = new InvalidNameFault();
fault.Request = request;
fault.Description = "Invalid name in FindEmployeeByLastName";
throw new FaultException<InvalidNameFault>(fault, "Invalid Name!");

Outcome

Any types returned to a client application using the generic FaultException<T> type will be included, regardless of service configuration settings. For example, the configuration property includeExceptionDetailInFaults will have no affect on the data returned in a FaultException<T> type. The following XML example shows a SOAP fault message that contains a fault contract named InvalidNameFault.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid Name!</faultstring>
      <detail>
        <InvalidNameFault xmlns="http://EmployeeService.FaultContracts/2006/09" 
                          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <Request>Fault</Request>
          <Description>Invalid name in FindEmployeeByLastName</Description>
        </InvalidNameFault>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

When a WCF client application processes the SOAP response shown in the previous XML example, it will be converted into a FaultException<T> that can be caught using the FaultContract type. The following code example shows how a client application can catch the exception associated with a specific fault contract.

catch (FaultException<EmployeeManager.InvalidNameFault> ex)
{
    string msg = "InvalidNameFault: " + ex.Detail.Description;
    msg += "\nRequest: " + ex.Detail.Request;
    MessageBox.Show(msg);
}

As shown in the previous code example, it is possible to catch a FaultException that contains a specific FaultContract, such as the InvalidNameFault. In addition, the Detail property of the FaultException type provides direct access to the properties that were defined in the original fault contract.

Show: