How to Handle WCF Fault Exception

The Unique Paul Smith picture The Unique Paul Smith · Jun 13, 2013 · Viewed 36k times · Source

I am trying to add more information regarding a SOAP fault in a open source client application. The client is setup to call "HandleFault" whenever it encounters any SOAP fault. The Handle Fault method is shown below:

   public static void HandleFault(Message message) {
        MessageFault fault = MessageFault.CreateFault(message, Int32.MaxValue);
        throw System.ServiceModel.FaultException.CreateFault(fault,
            typeof(PermissionDeniedFault),
            typeof(EndpointUnavailable),
            typeof(InvalidRepresentation),
            typeof(UnwillingToPerformFault),
            typeof(CannotProcessFilter),
            typeof(AnonymousInteractionRequiredFault)
        );
    }

Here is a portion of the SOAP Fault that is passed in as "message" when I try and do something like change a phone number to invalid format from the client.

  <s:Body u:Id="_2">
<Fault xmlns="http://www.w3.org/2003/05/soap-envelope">
  <Code>
    <Value>Sender</Value>
    <Subcode>
      <Value xmlns:a="http://schemas.xmlsoap.org/ws/2004/09/transfer">a:InvalidRepresentation</Value>
    </Subcode>
  </Code>
  <Reason>
    <Text xml:lang="en-US">The request message contains errors that prevent processing the request.</Text>
  </Reason>
  <Detail>
    <RepresentationFailures xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <AttributeRepresentationFailure>
        <AttributeType>OfficePhone</AttributeType>
        <AttributeValue>(123)456-7890</AttributeValue>
        <AttributeFailureCode>ValueViolatesRegularExpression</AttributeFailureCode>
        <AdditionalTextDetails>The specified attribute value does not satisfy the regular expression.</AdditionalTextDetails>
      </AttributeRepresentationFailure>
      <CorrelationId>11042dda-3ce9-4563-b59e-d1c1355819a4</CorrelationId>
    </RepresentationFailures>
  </Detail>
</Fault>

Whenever that Fault is encountered, the client only returns back "The request message contains errors that prevent processing the request.", I would like to include the "AttributeRepresentationFailure" node and child nodes before re-throwing the exception in the client.

The way I understand it is that I need to define a Fault class that contains those details to be deseralized, so that the call to "CreateFault" can return a . I've read through http://msdn.microsoft.com/en-us/library/ms733841.aspx but I just don't understand exactly how to define the class so that the client knows what type of fault is thrown.

UPDATE

In the client side handle fault method I added

 try
        {
            throw faultexcept;
        }
        catch (System.ServiceModel.FaultException<InvalidRepresentation> invalidRepresentationFault)
        {
            throw invalidRepresentationFault;
        }
        catch (System.ServiceModel.FaultException otherFault)
        {
            throw otherFault;
        }
        catch (Exception ex)
        {
            throw ex;
        }

The fault is always caught under the base fault class "otherFault". My InvalidRepresentation class is defined as below

 [DataContract(Namespace = Constants.Rm.Namespace)]
public class InvalidRepresentation 
{
    private string _attributeType;
    private string _attributeValue;
    private string _attributeFailureCode;
    private string _additionalTextDetails;

    [DataMember]
    public string AttributeType
    {
        get { return _attributeType; }
        set { _attributeType = value; }
    }

    [DataMember]
    public string AttributeValue
    {
        get { return _attributeValue; }
        set { _attributeValue = value; }
    }

    [DataMember]
    public string AttributeFailureCode
    {
        get { return _attributeFailureCode; }
        set { _attributeFailureCode = value; }
    }

    [DataMember]
    public string AdditionalTextDetails
    {
        get { return _additionalTextDetails; }
        set { _additionalTextDetails = value; }
    }


    public InvalidRepresentation() {

    }
}

Answer

Jason picture Jason · Jun 14, 2013

To add to Fredrik's answer, your Fault class can be whatever you need to convey the details of your custom error to the client. It doesn't have to inherit from another class or implement an interface. It just needs to be marked with the DataContract attribute.

As for catching it on the client side:

try
{
    ...
}
catch (FaultException<MathFault> mathFault)
{
    // handle a math fault
}
catch (FaultException<OtherCustomFault> otherFault)
{
    // handle another type of custom fault
}
catch (Exception ex)
{
    // regular exception handling
}