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 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.
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,
In this tutorial, we will use the following business flow :
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.
Here is the WorkfFlow state diagram of the above business flow:
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 :
Open Visual Studio and create a new project of type “WCF Workflow Service Application” as shown
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
Add these following variables as shown
By default Visual Studio creates an empty “ReceiveAndSendReply” activity, set the operation name to “CreateOrder” as shown
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
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
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
Select the “ReceiveRequest” and check the Properties window, enable the “CanCreateInstance” checkbox as shown
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.
Double click on the button next to CorrelationInitializers. In the “Add Initializer” type m_WorkflowIDasCorrelationHandle as shown
Next, in the XPath Query just hit dropdown and select the m_OrderID (this is the output parameter for CreateOrder Operation)
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/
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
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)
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
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
Set the CorrelatesWith to m_WorkflowIDasCorrelationHandle and set the input parameter to this correlation handle as shown
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
Drag and drop the TerminateWorkflow Activity and set the Reason to “done” as shown