Parent-Child Workflow Pattern Using Durable Duplex

A common design approach for implementing a workflow for a complex long-running process is to identify parts of business logic that can be isolated into smaller, simpler, and reusable workflows, and then coordinate their execution from the main workflow. For example, for purchase order processing, you might choose to define the shipping logic as a workflow (child), which in turn gets called from the main purchase order workflow (parent) when necessary.

In Windows Workflow Foundation in .NET Framework 4, there are no built-in features for “calling” one long-running workflow from another. Yet there are a number of implementation options that enable a developer to manually configure such behavior. Discussing all available options is not in scope for this sample; instead, the focus here is on one of the most common and generic approaches to implementing the “Call workflow” pattern – the durable duplex, and specifically in the context of long-running WCF Workflow Services (XAMLX workflows). The concept behind the durable duplex pattern is simple – the parent makes a call to an endpoint exposed by the child, passing in a context token (used for correlation) and a callback address along with the request message. Then after some time when the child completes it makes a call back to the parent to let the parent know that it has finished.

More information about setting up durable duplex manually can be found in the MSDN article on Durable Duplex (https://go.microsoft.com/fwlink/?LinkId=196632), and the related WF samples Durable Duplex sample (https://go.microsoft.com/fwlink/?LinkId=194430), and How to: Create a Workflow Service That Calls Another Workflow Service.

The main goal of this sample is to provide two custom activities based on the IActivityTemplateFactory interface, and designed to simplify the durable duplex implementation by automating the configuration process. The Workflow Callable Sequence activity is used in the child workflow, instead of the default Receive and Send activities generated upon creation of the workflow. The Call Workflow Sequence activity is used in the parent workflow to generate the activities and related configuration required to communicate with the child workflow. These activities are reusable and can be added to your Visual Studio toolbox.

The sample consists of two solutions:

  • The first solution (CallWorkflowActivities) contains the two activities mentioned above. To enable these activities for use in the Visual Studio Workflow Designer, it is sufficient to compile the solution and add the activities from the resulting assembly to the Visual Studio toolbox.

  • The second solution (DurableDuplex_with_CallWorkflowActivities) is a sample implementation of parent and child workflows communicating by using durable duplex configured by using the Workflow Callable Sequence and Call Workflow Sequence activities.

Note

Samples are provided for educational purposes only. They are not intended to be used in a production environment and have not been tested in a production environment. Microsoft does not provide technical support for these samples.

Prerequisites

This sample application is oriented toward readers who have the following experience or knowledge levels:

  • Basic knowledge of Internet Information Services (IIS)

  • Basic knowledge of WCF and Windows Workflow Foundation (WF) applications

  • Basic knowledge of Windows PowerShell

  • Basic knowledge of Microsoft SQL Server

In addition, the Hosting Services runtime features of Microsoft AppFabric 1.1 for Windows Server must be installed and the following features must be configured in order to run the DurableDuplex_with_CallWorkflowActivities solution:

  • Persistence store

  • Monitoring store

Sample Application Location and Files

Solution 1: CallWorkflowActivities

File name Description

CallWorkflowActivities.sln

Solution file for the CallWorkflowActivities solution

CallWorkflowActivities

Project folder

CallWorkflowActivities.csproj

Project file

Properties\AssemblyInfo.cs

Assembly info file

Activities\WorkflowCallableSequence.cs, Activities \CallWorkflowService.cs

Source files for the two IActivityTemplateFactory activities - WorkflowCallableSequence and CallWorkflowService

UI\CallWorkflowConfiguration.xaml, UI\CallWorkflowConfiguration.xaml.cs, UI\WebConfigContent.xaml, UI\WebConfigContent.xaml.cs, UI\WorkflowCallableSequenceConfiguration.xaml, UI\WorkflowCallableSequenceConfiguration.xaml.cs

UI design and source files for the dialogs used for configuration of the durable duplex

Code\Helpers.cs

Source code with supporting classes

Images\requiredBang.gif

Required field image file

Solution 2: DurableDuplex_with_CallWorkflowActivities

File name Description

DurableDuplex_with_CallWorkflowActivities.sln

Solution file for the DurableDuplex_with_CallWorkflowActivities solution

SampleChildService

Project folder for the Sample Child service

SampleChildService.csproj

Project files for the Sample Child service

Properties\AssemblyInfo.cs

Assembly info file

ChildWorkflow.xamlx

Child service workflow definition (XAMLX)

Web.config

Web configuration file for the Child service

SampleParentService

Project folder for the Sample Parent service

SampleParentService.csproj

Project files for the Sample Parent service

Properties\AssemblyInfo.cs

Assembly info file

ParentWorkflow.xamlx

Parent service workflow definition (XAMLX)

Web.config

Web configuration file for the Parent service

SampleClient

Folder for the test client

SampleClient.csproj

Test client project file

mainForm.cs, mainForm.Designer.cs, mainForm.resx, Program.cs

Source files for the main form and the application

Properties\Resources.Designer.cs, Properties\Resources.resx, Properties\Settings.Designer.cs, Properties\Settings.settings

Resource-related files and project settings

Properties\AssemblyInfo.cs

Assembly info file

app.config

Application settings file for the test client

Setting Up This Sample

  1. Start Visual Studio 2010 with administrative permissions.

    Note

    These steps demonstrate how to build and deploy the CallWorkflowActivities and DurableDuplex_with_CallWorkflowActivities solutions with Visual Studio 2010 and configure an application pool for use with these services.

  2. Open <samples>\ Samples\Integration\Call Workflow (DurableDuplex)\ CallWorkflowActivities\CallWorkflowActivities.sln, where <samples> is the path under which you have installed the AppFabric samples.

  3. On the Build menu, click Build Solution. Verify that the project builds with no errors in the output window.

    Note

    The assembly with the WorkflowCallableSequence and CallWorkflowService activities is now compiled and ready to be added to the toolbar (refer to the Running This Sample section for details).

  4. Open <samples>\ Samples\Integration\Call Workflow (DurableDuplex)\DurableDuplex_with_CallWorkflowActivities\ DurableDuplex_with_CallWorkflowActivities.sln, where <samples> is the path under which you have installed the AppFabric samples.

  5. When you receive the prompts to create the virtual directories for the SampleParentService and SampleChildService projects, click Yes.

  6. On the Build menu, click Build Solution. Verify that the three projects build with no errors in the output window.

  7. Start Internet Information Services (IIS) Manager: Click Start, click All Programs, click Microsoft AppFabric 1.1 for Windows Server, and then click Internet Information Services (IIS) Manager.

  8. Expand the server node in the tree view on the left, and then click Application Pools.

  9. Right-click the pool in the list that will be running the sample services (you can use one of the existing pools or create a new one), and then select Advanced Settings.

  10. Set .NET Framework Version to v4.0 by using the drop-down selection, and then click OK.

  11. In the left pane, expand Sites and then expand the Default Web Site.

  12. Locate the SampleChildService application, right-click and select Manage Application, and then select Advanced Settings.

  13. Update the Enabled Protocols property from http to http,net.pipe. Note that there is no space after the comma. Click OK to confirm the changes.

  14. In the Application Pool property browse to select the application pool that you configured in step 9.

  15. Locate the SampleParentService application, right-click and select Manage Application, and then select Advanced Settings.

  16. Update the Enabled Protocols property from http to http,net.pipe. Note that there is no space after the comma. Click OK to confirm the changes.

  17. In the Application Pool property browse to select the application pool that you configured in step 9.

    Note

    Steps 13 and 16 add the net.pipe protocol to the parent and child service applications, which is required for management of persisted workflow instances.

Running This Sample: Option 1

  1. Start Visual Studio 2010 with administrative permissions.

    Important

    There are two options for running this sample and steps for both are provided in this topic. Option 1 walks through the end-to-end experience of using the WorkflowCallableSequence and CallWorkflowService activities for calling a child workflow from a parent workflow, whereas Option 2 only looks at the final solution: a ready-to-run durable duplex implementation, completely bypassing the design experience. For more information, see the Demonstrates section below.

    Note

    The CallWorkflowActivities solution is designed to enhance the design-time experience of implementing a durable duplex. As such, there is nothing to “run.” However, these steps provide a walkthrough of using the activities in a simple solution where a parent workflow calls a child workflow.

  2. Create a new project of type WCF Workflow Service Application (this project template is located under the Workflow project types), and name the new project ChildService.

  3. Adding the sample custom activities to the toolbox: When the WF designer opens, right-click the toolbox, within the Messaging activities group.

  4. Select Choose Items and then click the System.Activities Components tab.

  5. Click Browse and navigate to <samples>\ Samples\Integration\Call Workflow (DurableDuplex)\ CallWorkflowActivities\ CallWorkflowActivities\bin\Debug. Then select the CallWorkflowActivities.dll assembly and click Open. (This is the assembly compiled in Step 3 of the Setting Up This Sample section of this document.) Notice the two new entries at the top of the System.Activities Components list.

  6. Click OK to add the CallWorkflowService and WorkflowCallableSequence activities to your toolbox. Your toolbox should look like the following screen shot.

  7. Implementing the ChildService workflow: In Solution Explorer, rename Service1.xamlx to ChildService.xamlx.

  8. In the main designer area for the ChildService, select the Sequential Service activity and press Delete.

  9. Drag the WorkflowCallableSequence activity from the toolbox onto the WF designer surface. This opens the configuration dialog that guides you through the task of setting up the ChildService as a participant in the durable duplex.

  10. Configuring the WorkflowCallableSequence: Fill out the properties as shown in the following screen shot, and then click OK.

  11. Updating the web.config file: The functioning of a durable duplex implementation is heavily dependent on correct web.config entries. The Web.config Updates screen automatically generates the entries required for your child workflow’s web.config file.

    Note

    The web.config file itself is not automatically updated. In the next step you will copy/paste the required entries to the web.config file.

  12. Click Copy to Clipboard & Close. This copies the highlighted required entries to the clipboard, ready for pasting into the web.config file. Click OK in the message box.

  13. Open the web.config file for the ChildService project and paste the content of the clipboard (from Step 12) just after the <system.serviceModel> tag:

    ...
      <system.serviceModel>
    
        <services>
          <service name="ChildService">
            <endpoint address="" binding="wsHttpContextBinding" contract="ICallChildService" name="ChildServiceICallChildServiceStartWorkflow" />
          </service>
        </services>
        <client>
          <endpoint binding="wsHttpContextBinding" contract="ICallChildService" name="ChildServiceICallChildServiceWorkflowCompleted" />
        </client>
    
        <behaviors>
      ...
    
  14. Completing the ChildService implementation: For simplicity, in the body of this workflow we will only assign the value of the request to the response (both are strings by default, however in an actual implementation these can be updated to data contracts).

    1. Drag a Delay activity from the toolbox onto the Body sequence. Configure the Delay activity with the following properties: Duration = New TimeSpan(0, 2, 0).

    2. Drag an Assign activity from the toolbox onto the Body sequence, just after the Delay sequence. Configure the Assign activity with the following properties: To = response; Value = request.

    3. Save the project.

  15. Enabling the service for IIS/WAS hosting: To configure the workflow for hosting in IIS/WAS and AppFabric, in Solution Explorer right-click the ChildService project (not the solution), and select Properties.

  16. Select the third configuration page, Web, and in the Servers section select Use Local IIS Web Server. Click Create Virtual Directory and then click OK in the pop-up message box. Save the project.

  17. Creating the ParentService workflow: In Solution Explorer, right-click the solution (not on the project) and select Add - > New Project. Select WCF Workflow Service Application for the project type and name the new project ParentService. Click OK.

  18. In Solution Explorer, rename Service1.xamlx to ParentService.xamlx.

  19. Drag the CallWorkflowService activity from the toolbox onto the WF design surface, straight after the SendResponse activity. This opens the configuration dialog for CallWorkflowService.

  20. Using the “…” button, browse to the ChildService.xamlx workflow definition created in the earlier steps, and then select wsHttpContextBinding to match the protocol selection from Step 10. The configuration window should look like the following screen shot.

    Note

    All settings for the request/response service contract and operation names have been automatically discovered from the child service definition.

  21. Click OK.

  22. Updating the web.config file: The Web.config updates dialog will open with the entries required to connect to the child service. Note that the actual child endpoint address, as well as the callback endpoint address require input.

  23. Click Copy to Clipboard & Close. This will copy the highlighted web.config entries to your clipboard, ready for pasting into the web.config file. Click OK in the pop-up message box.

  24. Open the web.config file of the ParentService project and paste the content of the clipboard straight after the <system.serviceModel> element.

    Note

    Notice the IMPORTANT comment in the XML – the parent service needs to also expose an endpoint for its clients. For the purpose of this sample, you can use the sample <endpoint> defined as part of the comment. Your web.config file should look like the following:

    ...
      <system.serviceModel>
    
        <services>
          <service name="Service1">
            <endpoint address="" binding="basicHttpBinding" contract="IService" />
            <endpoint address="ChildCallback" binding="wsHttpContextBinding" contract="ICallChildService" name="Service1ICallChildServiceWorkflowCompleted" />
          </service>
        </services>
        <client>
          <endpoint address="https://localhost/ChildService/ChildService.xamlx" binding="wsHttpContextBinding" bindingConfiguration="Service1ICallChildService_InitCallback" contract="ICallChildService" name="Service1ICallChildServiceStartWorkflow" />
        </client>
        <bindings>
          <wsHttpContextBinding>
            <binding name="Service1ICallChildService_InitCallback" clientCallbackAddress="https://localhost/ParentService/ParentService.xamlx/ChildCallback" />
          </wsHttpContextBinding>
        </bindings>
    
        <behaviors>
          <serviceBehaviors>
      ...
    
  25. Completing the ParentService implementation: The parent workflow will need to pass parameter values to the service call to the child service.

    1. To assign a value to the request, drag an Assign activity from the toolbox onto the Call Workflow sequence, just before the Send Request activity. Configure the Assign activity with the following properties: To = request; Value = data.ToString

    2. Save the project.

  26. Enabling the ParentService for IIS/WAS hosting: To configure the workflow for hosting in IIS/WAS and AppFabric, in Solution Explorer right-click the ParentService project (not the solution), and select Properties.

  27. Select the third configuration page –Web, and in the Servers section select Use Local IIS Web Server. Click Create Virtual Directory and then click OK in the pop-up message box. Save the project.

  28. Build the solution.

  29. Configuring IIS/WAS for hosting the ParentService and ChildService durable services: Start Internet Information Services (IIS) Manager: Click Start, click All Programs, click Microsoft AppFabric 1.1 for Windows Server, and then click Internet Information Services (IIS) Manager.

  30. In the left pane, expand Sites and then expand the Default Web Site.

  31. Locate the ChildService application, right-click and select Manage Application, and then select Advanced Settings.

  32. Update the Enabled Protocols property from http to http,net.pipe. (Note that there is no space after the comma). Click OK to confirm the changes.

  33. Locate the ParentService application, right-click and select Manage Application, and then select Advanced Settings.

  34. Update the Enabled Protocols property from http to http,net.pipe. (Note that there is no space after the comma). Click OK to confirm the changes.

  35. Run the WCFTestClient to start a parent workflow instance. Run the WCF Test Client application by executing the following command: C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\WcfTestClient.exe (for 32-bit platforms) or "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\WcfTestClient.exe" (for 64-bit platforms).

  36. Select Add->Add Service to add a reference to the parent service – https://localhost/ParentService/ParentService.xamlx.

  37. After the reference is added, double-click the GetData() method, and then in the left pane type 123 for the int parameter value. Click Invoke.

  38. Use the AppFabric Dashboard to check the status of the ParentService and ChildService instances. You will notice that after the ChildService is completed, the parent will also complete because it receives the completion notification from the child.

Running This Sample: Option 2

  1. Start Visual Studio 2010 with administrative permissions.

    Important

    There are two options for running this sample and steps for both are provided in this topic. Option 1 walks through the end-to-end experience of using the WorkflowCallableSequence and CallWorkflowService activities for calling a child workflow from a parent workflow, whereas Option 2 only looks at the final solution: a ready-to-run durable duplex implementation, completely bypassing the design experience. For more information, see the Demonstrates section below.

  2. Open <samples>\ Samples\Integration\Call Workflow (DurableDuplex)\DurableDuplex_with_CallWorkflowActivities\ DurableDuplex_with_CallWorkflowActivities.sln, where <samples> is the path under which you have installed the AppFabric samples.

  3. Make sure the SampleClient is set as the startup project by right-clicking on the SampleClient project, and clicking Set as StartUp Project.

  4. Press F5 to run the sample. The sample test client application will start.

  5. Click Call Parent Service.

  6. Watch the Workflow Instances text. It displays the start/completion events of the parent and child workflows. In this sample, the parent starts three instances of the child service in parallel, using the ParallelForEach activity, and completes when all three children have completed. You can also keep track of the running parent/child service instances by using the AppFabric Dashboard.

    Note

    The child workflow goes to sleep for two minutes after it is started. During this period all parent and child instances go to idle mode and are persisted to the persistence store. The completion events will occur after this two-minute period.

Removing This Sample

  1. Start Internet Information Services (IIS) Manager: Click Start, click All Programs, click Microsoft AppFabric 1.1 for Windows Server, and then click Internet Information Services (IIS) Manager.

  2. Expand the server node in the tree view on the left. Expand Sites, and then expand Default Web Site.

  3. Click the SampleChildService node and press Remove.

  4. Click Yes to confirm removing the selected application.

  5. Click the SampleParentService node and press Remove.

  6. Click Yes to confirm removing the selected application.

  7. If you have followed the instructions from Option 1 under “Running This Sample”, you will also need to:

    1. Click the ChildService node and press Remove.

    2. Click Yes to confirm removing the selected application.

    3. Click the ParentService node and press Remove.

    4. Click Yes to confirm removing the selected application.

Demonstrates

There are two options for running this sample and steps for both are provided in this topic. Option 1 is preferred over Option 2 because it walks through the end-to-end experience of using the WorkflowCallableSequence and CallWorkflowService activities for calling a child workflow from a parent workflow, which is the primary objective of this sample. Option 2 only looks at the final solution – a ready-to-run durable duplex implementation, completely bypassing the design experience.

Option 1 under “Running This Sample” demonstrates how to use the two custom activities in a project.

First, the child workflow service is created; the default Sequential service activity is deleted, and then replaced with the WorkflowCallableSequence “activity”. WorkflowCallableSequence is an activity template factory, which based on the user input generates and configures the messaging activities (Receive and Send) such that they support callback correlation. Callback correlation requires the request context to contain a unique context token used for correlation back to the parent, as well as the callback address for sending the completion notification to. The Receive activity initializes a callback correlation handle from the incoming request, while the Send activity follows that handle to send the completion notification back to the parent at the dynamic callback address passed in with the initial request.

The WorkflowCallableSequence logic also generates the web.config entries for the service, the service and client endpoints, and any required binding entries.

The next step creates the Parent workflow service. The CallWorkflowService activity template factory prompts for the child definition, inspects its configuration, and based on this it generates the messaging activities (Send and Receive) required for the durable duplex communication to the child. The Send activity initializes the callback correlation (logically, this is the step where the unique context token is generated and passed along with request to the child workflow), and then the Receive activity correlates the completion notifications coming back from the child workflow using the same context token (by correlating with the correlation handle initialized at the Send activity).

The CallWorkflowService logic also generates the web.config entries for the service, the service and client endpoints, and any required binding entries. Note the use of the clientCallbackAddress attribute in the definition of the custom binding configuration. This is the address that will be included in the request message to the client so that it can dynamically reply back to the correct caller (in this case, the parent workflow).

Option 2 under “Running This Sample” provides a ready-to-run durable duplex solution that was implemented using WorkflowCallableSequence in the child workflow and CallWorkflowService in the parent workflow.

The client makes a call to the parent service, which in turn starts three instances of the child service in parallel, using the ParallelForEach activity. The child service, after receiving the initial message from the parent, goes to sleep for two minutes (using a Delay activity), and after this period sends a completion notification back to the parent. The parent completes only when all instances of the child service have completed. Both the parent and child instances log entries to the Application event log, using “Samples” as the source. The client UI monitors the Application event log for this event source to display the completion events in the Workflow Instances text box.

  2012-09-12