One of the really important new features in Windows Workflow Foundation 4.5 is the capability to version workflows and workflow instances. You get to choose what you want to do, either keep running existing instances with their original workflow definition or upgrade them to the latest workflow definition.
What should you do, upgrade exiting instances or run multiple definitions side by side?
Both the upgrade to latest and keep running with the original definition make sense in different scenarios. If you find a bug in your workflow definition the update scenario is probably what you are looking for. However if your business contract conditions change it makes sense to keep the older workflow instances with the original workflow definition and start new new workflows with the new definition. Both make sense, it’s just a matter of the requirements.
In this blog post I am going to explain how to do an upgrade of an existing workflow instance. In a future blog post I will go into side by side execution.
The basic steps
When upgrading a workflow instance we are always concerned with the following basic steps”
- Create your initial workflow definition.
- Start one or more instances using the this workflow definition.
- Prepare the original workflow definition for update.
- Make some changes to the workflow definition.
- Create an update map between the original workflow definition and the new one.
- Update exiting workflow instances to reflect the new workflow definition.
Create your initial workflow definition
This is the simple step as anyone that has been using Windows Workflow Foundation 4 has already been doing this. For this example I am using a real simple workflow that prints the version number it was started with and the current version.
Start one or more instances using the this workflow definition
Again no big deal here, just run the workflow application.
Prepare the original workflow definition for update
In this step we prepare the workflow definition, the XAML file, for update using the DynamicUpdateServices.PrepareForUpdate() on an ActivityBuilder. This step adds a copy of the workflow definition in a DynamicUpdateInfo.OriginalActivityBuilder element so we can see the differences later when we are done. Right now we can use the workflow to run a workflow and everything would appear unchanged.
Make some changes to the workflow definition
In the workflow I am going to make a small change to reflect that it is workflow definition is version 1.1 and in the code I am going to use the same version 1.1.
If I try to resume the previously saved workflow definition this results in an VersionMismatchException.
Unhandled Exception: System.Activities.VersionMismatchException: The WorkflowIdentity (‘; Version=1.0’) of the loaded instance does not match the WorkflowIdentity (‘; Version=1.1’) of the provided workflow definition. The instance can be loaded using a different definition, or updated using Dynamic Update.
Create an update map between the original workflow definition and the new one
In order to upgrade the saved workflow instance we first need to create an update map. In this step we use the DynamicUpdateServices.CreateUpdateMap() function to create a map of the changes made since DynamicUpdateServices.PrepareForUpdate() was called. There is no way to create an update map based on anything else then the internal DynamicUpdateInfo. This means if you forgot to call DynamicUpdateServices.PrepareForUpdate() and save the workflow but instead just started making changes you are going to experience some problems. My first expectation was I could create an update map by comparing and older version of the workflow, for example from the TFS history, but that just isn’t possible using DynamicUpdateServices.CreateUpdateMap(). One solution here might be to use DynamicUpdateInfo.SetOriginalActivityBuilder().
Another slightly surprising thing is there is no native save functionality for a DynamicUpdateMap. In this case I am using a DataContractSerializer to save the update map in a way I can load it again.