Developing a WCF Service – Fault Exceptions AND FAULT Contracts

This next post about WCF will show how to integrate Fault Exceptions and Fault Contracts in your service.

As written in MSDN Fault Exceptions are used for "… mapping managed exception objects to SOAP fault objects and SOAP fault objects to managed exception objects …". This means that if you are looking for interoperability in your service development then you definitely should use this, because no Java client will understand a .NET exception.

You can read some more about it in this link Specifying and Handling Faults in Contracts and Services.

So, when using Fault Exceptions (or SOAP Faults) you have two alternatives:

  • Normal typed (or "un-typed") – You throw a regular FaultException which only contains general information about the SOAP Fault
  • Strongly-typed – You define your own SOAP Fault object, which can contain any kind of information you want about the SOAP Fault

Strongly-typed SOAP Faults are then used when you wish to give to the client some more information and context about the cause of the exception. They also couldn’t be much easier to define in WCF, because they are no more, no less than another Contract in the service definition, which are semantically called Fault Contracts.

As such, you define a Fault Contract in your service definition in the following way:

/// <summary>

/// Strongly-typed fault.

/// </summary>

[DataContract]

public class ArgumentFault

{

    #region Get / Set

 

    /// <summary>

    /// 

    /// </summary>

    [DataMember]

    public String Operation { get; set; }

 

    /// <summary>

    /// 

    /// </summary>

    [DataMember]

    public String Argument { get; set; }

 

    /// <summary>

    /// 

    /// </summary>

    [DataMember]

    public String Message { get; set; }

 

    #endregion

}

You then define that an operation can throw this type of fault contract by appending the following to your operation:

[FaultContract(typeof(ArgumentFault))]

[OperationContract]

Customer GetCustomer(Int32 customerId);

Now in the service implementation when you want to throw the defined fault contract you do like this:

public Customer GetCustomer(int customerId)

{

    if (customerId <= 0)

    { // Not possible

        throw new FaultException<ArgumentFault>(new ArgumentFault()

        {

            Operation = MethodBase.GetCurrentMethod().Name,

            Argument = "customerId",

            Message = "Argument must be greater than zero."

        });

    }

 

    return Customers.First(customer => 

    {

        return customer.Id == customerId;

    });

}

This is better than just doing:

throw new FaultException(MethodBase.GetCurrentMethod().Name + 

               ": customerId - Argument must be greater than zero.");

 

In the client application for catching this Fault Exception, you code should be:

try

{    // Get customer

    Customer singleCustomer = proxy.GetCustomer(customers[0].Id);

    Console.WriteLine("SingleCustomer: Id - {0} / Name - {1}.",

                singleCustomer.Id, singleCustomer.Name);

 

    // Force fault

    singleCustomer = proxy.GetCustomer(0);

}

catch (FaultException<ArgumentFault> ex)

{

    Console.WriteLine("FaultException<ArgumentFault>: {0} - {1} - {2}",

            ex.Detail.Operation, ex.Detail.Argument, ex.Detail.Message);

}

catch (FaultException ex)

{

    Console.WriteLine("FaultException: {0}", ex.Message);

}

 

Again the full code is available here:

 

Related List of articles

Developing a WCF Service

Developing a WCF Service – Calling the hosted service