Friday, 1 October 2010

Workflow 4.0 a brief overview

This is a very simple post about my recent findings on using workflow 4.0 (WF 4.0). I build a simple WF which managed expense approval.
Server Specs
Windows server 2008 R2 standard (Virtual server with 4gigs RAM)

  • Visual Studio 2010
  • SQL 2008
  • IIS and Appfabric
  • Visual Studio 2010
  • Workflow 4.0
  • Entity Framework 4.0
  • Linq
  • SQL 2008
  • IIS
  • AppFabric
  • SMTP
Initial setup steps:
Install Visual Studio 2010 Professional
Install appFabric (More on appFabric configuration in a later post hopefully)
Setup monitoring and persistence (I used the default settings - ie. root web.config in IIS holds settings for any child sites.)

Visual Studio 2010 Development:
I decided that I wanted to try this technology with a useful purpose in mind. It is not a full scale app. but most of the basic building blocks are there.

The app. I build is an expense approval app. using workflow 4.0 (WCF Workflow Service Application):

This project allows you to build a workflow and expose it as a WCF service. I ended up at this decision as I started developing workflow using System.Activities.WorkflowApplication. This worked well until I tried to use a delay timer in my WF. I was persisting my workflow successfully but after the expected time period for my timer had elapsed, the workflow was still "asleep" in my persistence store.

Following this I hunted the web for a better soln. I didn't necessarily need a delay timer for anything at this stage but, because the WF was unusable with a delay timer I thought I should keep hunting for a better solution. I came across loads of posts (some wrong, some out of date - this was very frustrating).

I decided to try and use the WorkflowServiceHost ( as it says on the "tin" that this will manage the re-hydration of my workflows from the persistence store.

I can't remember where I got to with the WorkflowServiceHost but in the end after I posted a question on this post:

and Stuart pointed me in the right direction I moved to my current, as mentioned above, setup.

This being windows server 2008 R2 with full appFabric monitoring and persistence installed. I thought, why try and reinvent the wheel when this great infrastructure is provided more or less out of the box.

So, back to the actual workflow development. Here is an overall picture of my workflow. It needs refactoring but i'll plonk it here for now and come back to it later. (Certain parts, like the duplication in the parallel activity need refactoring).

Note: I wont be going into to much the detail with regard to my code as i'd rather explain the steps taken and a higher level.

The workflow receives an ExpenseRequest. If amount of this ExpenseRequest is under £100 the expense gets auto approved and the expense submitter is notified.

If the expense is over £100 a notification is sent to a manager for approval. If said manager does not action this request within a period of time the workflow re-hydrates from the persistence store and reminds the manager.

I tested this re-hydration (with my WF hosted bty AppFabric but submitting an expense for over £100 and letting the expense notification reach the manager (Note: the delay activity for the reminder was set to 10 minutes at this point)).

I then rebooted the server and waited the remainder of time that the delay timer required.

After the timer was due to expire the workflow came alive and sent the reminder to the manager. Good times!!

So anyway, The workflow "code" functions correctly. Some points about it that I will point out are.

The workflow (workflow as a Wcf service hosted in AppFabric (IIS)) is consumed by 3 clients:
  • One is a console app. that I have just for some initial setup testing.
  • The second is a windows forms client that is used to submit the expense request.
  • The third is a web app. that is used to approve or reject the expense.

Note: the manager links to the web app. from a link in the Smtp email that the workflow sends out.

If you right click on the workflow ExpenseService.xalmx file and select "view in browser" you can see the Wcf definition and Wsdl for your workflow. This is good to know as we now know we can definitely host our workflow in IIS / AppFabric. More good times!!

In my clients I added a service reference to my Workflow .xamlx service. Here are the steps to to this:
Note: that I selected to "generate asynchronous operations" as I dont want my client apps. to hang around waiting for a "long running process" to complete when all I really care about is whether my ExpenseRequest was sent correctly.

Once I have my xamlx service referenced in my client apps. I need to write some code to instantiate it. first of all I need these lines:
private static ExpenseServiceClient client = new ExpenseServiceClient();
request.Expense = new Expense();
request.Expense.Amount =200;
request.Expense.Title = "";
client.BeginSubmitExpense(request, OnStartCompleted, null);

As I said, I am doing this asyc so I only care that my request was successful. Do be sure of this I subscribe to the IAsyncResult.
The code looks like this:
SubmitExpenseResponse result = (SubmitExpenseResponse)client.EndSubmitExpense(asr);
Within the method that waits for the IAsyncResult I have some try catches.
catch (CommunicationException)
catch (TimeoutException)
catch (Exception)
I can then decided what do in my client app. when something goes wrong.

You can probably see in my workflow that there are some custom activities like:
AutoScreenExpense, NotifyExpenseSubmitter, RequestManagerAction, SaveExpense, UpdateExpense. These are my own activities that inplement System.Activities.CodeActivity. AutoScreenExpense is a flowchart xaml workflow that I have built that just takes are of the £100 limit decision mentioed earlier.

After you build your custom activities they will appear in the toolbox.

AutoScreenExpense is a separate workflow that I have exposed as a custom activity inside the ExpenseService.xamlx workflow. Nice!To write a code based activity you can either implement System.Activities.CodeActivity or System.Activity.NativeActivity.As you can see I implement CodeActivity. Also note that this activity has a public InArgument which is the ExpenseRequest coming into the activity. the expenserequest is then mapped to my Entity Framework 4.0 entity and then saved and a response is sent back to the workflow.

Another thing I nearly forgot is that the way to get data into and throught a workflow is to use arguements or variables. In this case, I think because I have used a xamlx project type, I only have access to variables as follows:

you can see my ExpenseRequest variable another one for response and a boolean that is used internally by my workflow. Also, I have an ExpenseIDHandle that is used for correlation so that the workflow know which instance of a workflow to work with when a caller asks it to do something.

I mentioned that I am using Entity Framework 4.0 to manage my database updates. I have a couple of tables in an SQL 2008 database. One holds the record of the expense to be approved and the other is just a lookup table:

Obviously this is not very fancy but I plan on building on it later.

So now I have a workflow that I can host in IIS and AppFabric. In my next post I will do this.
Over and out!!

Ps. If I have got anything wrong here please let me know