Consuming Faults, Part 1

The next two episodes are about consuming fault messages and exceptions. Day one covers consuming fault messages and possibly producing an exception. Day two covers consuming exceptions and possibly producing a fault message. Both directions work by going through an instance of FaultConverter. You can override this conversion behavior in a custom channel by subclassing FaultConverter and returning an instance whenever GetProperty<FaultConverter> is called on your channel. We also have a default FaultConverter that handles a number of cases.

When your channel receives a fault, there are three things you can do. If the fault message is unintelligible, you might just give up and treat the fault message as you would any other bad message. Assuming that the fault message is valid, you'll want to either handle a recoverable fault or propagate an unrecoverable fault. You'll also want to handle any fault that higher levels of the protocol stack will find unintelligible. That just leaves dealing with propagating a fault as an exception.

We'll need two methods from FaultConverter to take care of this last case.

 public bool TryCreateException(Message message, MessageFault fault, out Exception exception);
protected abstract bool OnTryCreateException(Message message, MessageFault fault, out Exception exception);

TryCreateException takes in a fault message and potentially produces an exception. Override OnTryCreateException to handle fault messages and return whether you were successful. If you claim that your FaultConverter handled the fault but don't provide an exception, then we'll throw an InvalidOperationException. The same thing happens if your FaultConverter claims it didn't handle the fault but provides an exception anyway.

The default fault converter can handle eight different faults in its OnTryCreateException, some of which only apply to specific addressing modes. I've talked about several of these before, but here's the complete list.

1.
MustUnderstand becomes a ProtocolException
2.
ActionNotSupported becomes an ActionNotSupportedException
3.
DestinationUnreachable becomes an EndpointNotFoundException
4.
InvalidAddressingHeader becomes a MessageHeaderException (InvalidCardinality only) or a ProtocolException
5.
MessageAddressingHeaderRequired becomes a MessageHeaderException
6.
MessageInformationHeaderRequired becomes a ProtocolException
7.
InvalidMessageInformationHeader becomes a ProtocolException
8.
EndpointUnavailable becomes a ServerTooBusyException

Next time: Consuming Faults, Part 2