Recently somebody asked me how a workflow could invoke another workflow that is loaded as XAML from a file or a database.  This is a common request so I’ve added an activity to Microsoft.Activities to support this.

Update: If you want tracking to include data from the child workflow be sure to update to Microsoft.Activities.1.8.3 or later. See Tracking Child Workflow with InvokeWorkflow for details

Update 2: 2011-09-26 The Sample has been updated to support loading of activity assemblies and setting the XamlXmlReader LocalAssembly

Download the Source for this example from MSDN Code Gallery – WF4 - How To Invoke a Child Workflow as XAML

Scenario: Load an Activity from a XAML Text File and Invoke It

Given

  • A child activity deployed as XAML text in a file which will run to completion when invoked (no bookmarks)
  • A parent Workflow which needs to invoke the child activity that is not known until runtime

When

  • The parent workflow is invoked

Then

  • It loads the child activity from XAML text
  • and Invokes it passing arguments to the child activity
  • and receives output from the child activity when it completes

Step 1: Construct an Example using an Early Bound (Compile Time) Workflow Dependency

For this simple example, I’ve create a child activity named Increment.xaml which accepts a number “Num” and increments it by one.  This will be our child workflow.

image

The Parent Workflow is InvokeChild.xaml and it declares two variables StartingNumber (initialized to 3) and TheNumber which will be passed to the child workflow

image

For this working example, I’ve used the Increment activity and referenced it in the XAML at compile time.  I want to have a good starting point for our example and as you can see it works.

image

Step 2: Add Microsoft.Activities to the project

In the latest release of Microsoft.Activities we have added several new activities to support this scenario

  • LoadActivity – loads an activity from a XAML file
  • InvokeWorkflow – Invokes an activity using WorkflowInvoker (no bookmarks supported)
  • LoadAndInvokeWorkflow – Loads and Invokes using the other two activities
  • DictionaryActivities – Invoking workflows requires you to create and manipulate dictionaries so we’ve added a set of Dictionary activities to support this

When I want to use Microsoft.Activities in a project I create a folder called Reference Assemblies, Download the latest release from http://wf.codeplex.com and add the assemblies to that folder.  The I add a reference to Microsoft.Activities.dll.

Step 3: Change Increment.xaml to be treated as deployed content

Now I need to tell Visual Studio to treat Increment.xaml as content.  To do this, in Solution Explorer, click on Increment.xaml and set the properties

  • Build Action: Content
  • Copy to Output Directory: Copy Always
  • Custom Tool: (empty)

Step 4: Use the Microsoft.Activities.LoadAndInvokeWorkflow activity

Now I need to replace the Increment activity I added earlier with the LoadAndInvokeWorkflow activity.  Sometimes Visual Studio doesn’t automatically add the activities from Microsoft.Activities to my toolbox.  You can always add them manually if you need to.

  1. Delete the existing Increment activity
  2. Create a new Variable of type Dictionary<string, object> to hold the Input arguments named ChildArguments initialized to New Dictionary(Of String, Object)
  3. Create another new Variable of type IDictionary<string, object> named ChildResult
  4. Drop an AddToDictionary activity and set it to use types String, Object and set the properties
    • Dictionary: ChildArguments
    • Key: “Num”
    • Value: TheNumber
  5. Drop a LoadAndInvokeWorkflow activity and set the properties
    • Input: ChildArguments
    • Path:  “Increment.xaml”
    • Result: ChildResult
  6. Drop an Assign activity and set the properties
    • To: TheNumber
    • Value: Convert.ToInt32(ChildResult("Num"))

Step 5: Test It

No surprise here – it works when you run it if you did all the steps correctly.

One note – if you were going to run the activity hundreds of times you should not use LoadAndInvokeWorkflow but instead use LoadActivity to load it once and then InvokeWorkflow to invoke it over and over again.

Happy Coding!
Ron Jacobs
http://blogs.msdn.com/rjacobs
Twitter: @ronljacobs http://twitter.com/ronljacobs