Complete code is available at Developer Code Samples

In some scenarios we need a Workflow to interact with ASP.NET Web application and external WCF Services. In this blog, I want to discuss how I approached it. 

Workflow (WF) Services are WCF Services hosted within Workflow. External applications can consume these WCF Services to create a new instance of workflow or change the state of existing workflow instance.

When external applications call these WCF Services, WF Services invokes them on the right WF instances i.e. if there are more than one order waiting for manager approval and manager approves the one of them, WF Service will invoke the “approve activity” on that specific workflow instance. WF Services knows which instance of WF the WCF call belongs to (using the Correlation Handle).        

Correlation Handle

Correlation Handle will help WF Service to match the incoming WCF message to the right workflow instance. In the below example, we have three WF instances and client is sending WCF messages to only to instance #1 and #3 at the same time. Depending on the correlation value, WCF messages are executed on the right Workflow instance.

correlateson_2

 

The correlation handle is returned by the WF Services when workflow instance is created. Using this correlation handle clients call different WCF operations on the specific instance of the workflow,

UML

Workflow Example

In this tutorial, we will use the following business flow :  

  1. Customer creates an order at a website
  2. Website creates a workflow instance (on another machine)
  3. Workflow instance has to talk to external WCF services (inventory WCF Services )
  4. Workflow waits for approval from Sales Manager
  5. Manager can check the status of all pending orders on the website
  6. Manager approves or rejects orders on the website

Here, when a new order is created, the website calls a WF Service’s WCF Operation and starts a new Workflow instance on a remote machine. Next, the website calls another regular WCF operation to get the list of pending orders. Once the manager approves/rejects the order, the website calls another WF Service’s WCF operation to approve or reject that specific order.     

WebApp

State Diagram

Here is the WorkfFlow state diagram of the above business flow:

WF_StateDiagram

In this tutorial, ASP.NET Web application will invoke a WF Service (1) to create a new Order. WF instance will call an external WCF Service (2) to determine the inventory status. Later ASP.NET Web application will make another WF Service call (3) to approve or reject the order.

Here is the high level Workflow diagram. The Workflow is divided into four sequences :

  1. New Order
  2. Check Inventory
  3. Wait for Manager Approval or Reject
  4. Close Order

 

WF_Diagram_2

Step 1 : Create WF Service

Open Visual Studio and create a new project of type “WCF Workflow Service Application” as shown

WF_New_Project

Step 2 : Add variables to WF Service

Double click on the “Service1.xamlx”.  Before we add activities to this WF, we will add WF instance scope variables. Click on the “Variables” tab at the bottom left as shown

WF_Variables_4

Add these following variables as shown

Variable Name

Variable Type
m_OrderName String
m_OrderID Guid
m_bInventory Boolean
m_WorkflowIDasCorrelationHandle CorrelationHandle

WF_Variables_5

Step 3 : Create WCF Operation for creating new orders

By default Visual Studio creates an empty “ReceiveAndSendReply” activity, set the operation name to “CreateOrder” as shown

WF_CreateOrder_1Step 4 : Add input parameters to WCF Operation

To create order we need order details. In this tutorial, we just need order name to create an order. So lets set string as a input parameter.

Double click on the “View message…” or “View parameter…”     within the ReceieveRequest scope and add OrderName as shown

WF_CreateOrder_INPUT_Parameter

Next, in the “Assign To” set it to the our WF variable m_OrderName. Just start typing in the “Assign To”, Visual Studio will show all the available variables as shown

WF_CreateOrder_INPUT_Parameter_1

Step 5 : Add output parameters to WCF Operation

When ASP.NET application is approving or rejecting an order, it has to send an unique ID (that can identify the order) to WF Services, so that WF Service can act on that specific order.

This unique ID in WF Services is called CorrelationHandle. This can be anything, in this tutorial we will use WorkflowID as our unique ID.

So when ASP.NET Application creates a new order, we will return the WorkflowID as a return parameter.  And ASP.NET can send this WorkflowID when approving or rejecting the order.

Double click on the “View message…” or “View parameter…” within the SendReplyToReceieve scope and add m_OrderID as shown

WF_CreateOrder_OUTPUT_Parameter

Step 6 : Allow the CreateOrder (WCF Operation) to create a new instance of WF

Select the “ReceiveRequest” and check the Properties window,  enable the “CanCreateInstance” checkbox as shown

WF_CanCreateInstance

Step 7 : Set Correlation Handle to WorkflowID

We need to let the WF Service know that we want WorkflowID as our Correlation Handle. Correlation Handle will help WF Service to pick the right WF instance when the ASP.NET Web application is calling for Approve/Reject order.

Select the “SendReplyToReceive” and check the Properties window.

WF_CorrelationInitializers

Double click on the button next to CorrelationInitializers. In the “Add Initializer” type m_WorkflowIDasCorrelationHandle as shown

WF_CorrelationInitializers_1

Next, in the XPath Query just hit dropdown and select the m_OrderID (this is the output parameter for CreateOrder Operation)

WF_CorrelationInitializers_2

Step 8 : Calling external WCF Services from WF Services

Add the “Service Reference” to the project and rebuild the project. (note only after rebuild the project you can see the WCF services in the toolbox).

Here in this tutorial, add Service Reference to FishTankInventoryWCFServices and after rebuilding the project, we will see it in the Toolbox as shown

Complete code is available at Developer Code Samples @ http://code.msdn.microsoft.com/

toolbox_for_checkinventory_1

Drag and drop the “CheckInventory” WCF Services

To assign the input and output parameters, select “CheckInventory” and check the Properties window. Set the result to our WF instance variable m_bInventory and input parameter to m_OrderName

checkInventory_parameters

Step 9 : Add IF-Activity and Parallel-Activity

Drag and Drop the IF and Parallel activity as shown. And add two ReceiveAndSendReply to the Parallel activity. The If-Activity condition is the response from the inventory WCF Services (m_bInventory)

if_activity

Step 10 : Set input and output parameters for two WCF Operations

Follow the steps #4 and #5 and set the input and output parameters. The input parameters is GUID (WorkflowID – which also our Correlation Handle) as shown

WF_approve_input_parameters 

Step 11 : Set Correlation Handle for second WCF Operation

For the CreateOrder, we didn’t add any Correlation Handle for the Receive as CreateOrder is going to create a new instance of WF. But for the ApproveOrder and RejectOrder, we need to act on existing WF instance. So we need to set the correlation so that WF Service, when it receives the ApproveOrder or RejectOrder, executes them on the right instance of workflow.

Select “Receive” and check the Properties window. Double click on the CorrelatesOn as shown

 correlateson

Set the CorrelatesWith to m_WorkflowIDasCorrelationHandle and set the input parameter to this correlation handle as shown

correlateson_1

 

Step 12 : Exit from Parallel Activity

Parallel Activity is design to exit only after all its branches are executed. In our case, we are looking for either approve or reject. Once we get anyone of these, we need to exit from the Parallel Activity and go to next activity.

Parallel Activity has a variable called “CompletionCondition”  Once this value is set to true, it exits without waiting for other branches to execute. We set the CompletionCondition to a variable (parallel activity scope) and set this to true when we get Approve or Reject call from client.

To set the variable value to true, use the Assign Activity as shown

Parallel_exit_1

Parallel_exit

Step 13 : Terminate the WF Instance

Drag and drop the TerminateWorkflow Activity and set the Reason to “done” as shown

wf_terminate

Complete code

Complete code is available at Developer Code Samples