Consuming Faults, Part 2

Picking up from last time, we were going to look at consuming exceptions to possibly produce a fault message. The same machinery is used here as for the reverse conversion process. Exceptions go through an instance of FaultConverter, you can create your own FaultConverter in a custom channel to control the behavior, and we have a default FaultConverter for a variety of common exception types.

Here's the entire interface for FaultConverter, including the two methods that we used last time for consuming fault messages.

 public abstract class FaultConverter
{
   protected FaultConverter();

   public static FaultConverter GetDefaultFaultConverter(MessageVersion version);
   protected abstract bool OnTryCreateException(Message message, MessageFault fault, out Exception exception);
   protected abstract bool OnTryCreateFaultMessage(Exception exception, out Message message);
   public bool TryCreateException(Message message, MessageFault fault, out Exception exception);
   public bool TryCreateFaultMessage(Exception exception, out Message message);
}

The two methods of interest for today are TryCreateFaultMessage and OnTryCreateFaultMessage. TryCreateFaultMessage takes in an exception and potentially produces a fault message. Override OnTryCreateFaultMessage to handle exceptions and return whether you were successful. Unlike TryCreateException, TryCreateFaultMessage does not reject a null exception argument. This means that you need to do the check yourself if needed. However, the output of TryCreateFaultMessage has the same level of screening as TryCreateException. If you claim that your FaultConverter handled the exception but don't provide a fault message, then we'll throw an InvalidOperationException. If your FaultConverter claims it didn't handle the exception but provides a fault message anyway, we'll again throw an InvalidOperationException.

There are four exception types that the default fault converter will handle to produce specific fault messages.

1.
The private exception type for MustUnderstand (this will look like a CommunicationException to you) becomes a MustUnderstand fault
2.
ActionNotSupportedException becomes an ActionNotSupported fault
3.
The private exception type for ActionMismatch (this will look like a ProtocolException to you) becomes an ActionMismatch fault
4.
MessageHeaderException becomes an InvalidAddressingHeader fault if generated by a duplicate header and a MessageAddressingHeaderRequired fault otherwise

ActionMismatch and MessageHeaderException require WS-Addressing 1.0 for support. ActionNotSupportedException requires either of the versions of WS-Addressing. MustUnderstand works even if you're not using WS-Addressing.

Next time: 2006 Year in Review