Exception Management

patterns & practices Developer Center

Correct exception handling in your WCF application prevents sensitive exception details from being revealed to the user, improves application robustness, and helps avoid leaving your application in an inconsistent state in the event of errors.

Consider the following guidelines:

  • Use structured exception handling.
  • Do not divulge exception details to clients in production.
  • Use a fault contract to return error information to clients.
  • Use a global exception handler to catch unhandled exceptions.

Each of these guidelines is described in the following sections.

Use structured exception handling

Use structured exception handling and catch exception conditions. Doing this improves robustness and avoids leaving your application in an inconsistent state that may lead to information disclosure. It also helps protect your application from denial of service (DoS) attacks.

In C#, you can use the try/catch blocks and finally construct to implement structured exception handling. You can protect code by placing it inside try blocks, and implement catch blocks to log and process exceptions. Also, use the finally construct to ensure that critical system resources such as connections are closed, whether an exception condition occurs or not.

Additional Resources

Do not divulge exception details to clients in production

Do not divulge exception error details to clients in production. Instead, develop a fault contract and return it to your client. When exceptions occur, return concise error messages to the client and log specific details on the server. Do not reveal internal system or application details—such as stack traces, SQL statement fragments, and table or database names—to the client. Ensure that this type of information is not allowed to propagate to the end user or beyond your current trust boundary. If you expose any detailed exception information to the client, a malicious user could use the system-level diagnostic information to learn about your application and probe for weaknesses to exploit in future attacks.

By using the FaultContract attribute in a service contract, you can specify the possible faults that can occur in your WCF service. This prevents exposing any other exception details to the clients. To define a fault contract, apply the FaultContract attribute directly on a contract operation, specifying the error detailing type as shown below:

[ServiceContract]
interface ICalculator
{
   [OperationContract]
   [FaultContract(typeof(DivideByZeroException))]
   double Divide(double number1,double number2);
}

In the following example, the FaultContract attribute is limited to the Divide method. Only that method can throw that fault and have it propagated to the client.

class MyService : ICalculator
{
   public double Divide(double number1,double number2)
   {

      throw new FaultException<DivideByZeroException>(new DivideByZeroException());
   }
}

Additional Resources

Use a fault contract to return error information to clients

Use a fault contract to define the exceptions in your service and return error information to clients. By using the FaultContract attribute in a service contract, you can specify the possible faults that can occur in your WCF service. If there is an exception in your WCF service operation, use the FaultContract attribute to generate a specific SOAP fault message that will be sent back to the client application. The FaultContract attribute can only be used in operations that return a response. You cannot use this attribute on a one-way operation.

The following procedure shows how to use the FaultContract attribute to return error information.

  1. Define the type to pass the details of SOAP faults as exceptions from a service back to a client.

    [DataContract]
    public class DatabaseFault
    {
        [DataMember]
        public string DbOperation;
        [DataMember]
        public string DbReason
        [DataMember]
        public string DbMessage;
    }
    
  2. Use the FaultContract attribute in the ListCustomers method to generate SOAP faults.

    [ServiceContract]
    public interface ICustomerService
    {
        // Get the list of customers
        [FaultContract(typeof(DatabaseFault))]
        [OperationContract]
        List<string> ListCustomers();
        …
    }
    
  3. Create and populate the DatabaseFault object with the details of the exception in the Service implementation class, and then throw a FaultException object with the DatabaseFault object details.

    catch(Exception e)
    {    DatabaseFault df = new DatabaseFault();
        df.DbOperation = "ExecuteReader";
        df.DbReason = "Exception in querying the Northwind database.";
        df.DbMessage = e.Message;
        throw new FaultException<DatabaseFault>(df);
    }
    

Use a global exception handler to catch unhandled exceptions

Use a global exception handler to catch unhandled exceptions and prevent them from being propagated to the client. You can handle the unhandled exceptions in a WCF service by subscribing to the Faulted event of a service host object. By subscribing to this event, you can determine the cause of a failure, and then perform the necessary actions to abort or restart the service.

The following code snippet shows how to subscribe to the Faulted event:

// hosting a WCF service 
ServiceHost customerServiceHost;
customerServiceHost = new ServiceHost(…);
…
// Subscribe to the Faulted event of the customerServiceHost object
customerServiceHost.Faulted += new EventHandler(faultHandler);
…
// FaultHandler method - invoked when customerServiceHost enters the Faulted state
void faultHandler(object sender, EventArgs e)
{     // log the reasons for the fault…
}

Additional Resources