WWF Logo

Image by ponChiang via Flickr

Note: This blog post is written using the .NET framework 4.0 RC 1

 

Using the ReceiveAndSendReply activity template and the WorkflowServiceHost it is easy to create a workflow service. Other applications can communicate with the workflow just as if it is a regular WCF service, they never need to know the difference. Most of the configuration is quite straightforward. Select the Receive activity and configure it and do the same with the SendReply activity. Most the settings normally done using a ServiceContract or an OperationContract are there.

But what about faults?

Turns out there is no property anywhere to specify anything about a possible fault being returned.

 

Throwing a FaultException

When a FaultException is thrown in a workflow service pretty much the expected thing is done. The exception is send to the client as a soap fault and the client, assuming .NET here, can catch it as a FaultException. No big deal so far.

How about a FaultException<T>?

Normally when you want to add extra information with a fault you create an extra class and decorate the service contract with a FaultContract attribute specifying the fault returned. This gets added to the service metadata and doing an Add Service Reference creates the required type on the client. But with a workflow service there is no service contract class we can add the attribute to. And there is no property we can use for this purpose either. So how do we specify the fault contract with a workflow service?

The trick is to add a second SendReply to the workflow associated with the same Receive activity. The second SendReply activity returns the fault contract and this is how it gets into the workflow service metadata. Adding the second SendReply is easy, just right click the Receive activity and select Create SendReply and the activity is there. Next create a variable to hold the fault information.

The FaultDetail I am using is real simple, all it does is send the data received back to the client.

using System.Runtime.Serialization;
 
namespace ServicesAndFaults
{
    [DataContract]
    public class FaultDetail
    {
        [DataMember]
        public int Data { get; set; }
    }
}

 

With this second SendReply activity, creating and throwing a FaultException the workflow looks like this:

With the following expression used to initialize the fault

The SendReply activity that is returning the error is configured like this:

With this setup adding a Service Reference from a client application and using the following code has the expected result

static void Main(string[] args)
{
    var proxy = new ServiceClient();
 
    try
    {
        Console.WriteLine(proxy.GetData(42));
    }
    catch (FaultException<FaultDetail> ex)
    {
        Console.WriteLine("FaultException<FaultDetail> with {0}", ex.Detail.Data);
    }
    catch (FaultException ex)
    {
        Console.WriteLine(ex);
    }
 
    Console.ReadLine();
}

 

The output from the workflow in the service console application look like this. Note that the last message, of the workflow finishing, never appears. Not really surprising as we throw an error that is never caught and terminates the workflow.

 

But I want to keep my workflow alive!

Sometimes the behavior above is just fine but at other times it is not. Suppose you have been working on an order for months do you really want to terminate all that work just because of a single exception? Probably not.

The second way to return a fault to the calling client is just to return the FaultException or FaultException<T>  from the SendReply activity used to define it. The client will never know the difference but the workflow will keep on running perfectly happy. So all I needed to do is remove the Throw activity and let the second SendReply do its work.

This time the service console application output look like this:

 

Nice to know but this feature of Windows Workflow Foundation 4 does leave something to be desired in the discoverability department. Here is another document describing how to use this feature.

 

Download the source code ServicesAndFaults.zip

 

Enjoy!

www.TheProblemSolver.nl

Wiki.WindowsWorkflowFoundation.eu