February 2012

Volume 27 Number 02

Windows Workflow Foundation 4.5 - What's New in Windows Workflow Foundation 4.5

By Leon Welicki | February 2012

At the BUILD conference last September (buildwindows.com), Microsoft unveiled the next version of Windows Workflow Foundation (WF 4.5) and made available a public preview as part of the Windows 8 Developer Preview (msdn.microsoft.com/windows/apps/br229516). In this article, I’ll walk through the key new features added in WF 4.5. Given the general scope of the article and the size of the feature set, each discussion will be brief, but I hope you’ll get excited enough to download the Windows 8 Developer Preview and start playing with WF 4.5.

WF: Yesterday, Today and Tomorrow

WF 4 shipped in 2010 to a great reception from the developer community. WF 4 included significant advances over its predecessor (WF 3.5): improved runtime, better overall performance, simplified activity authoring, full Windows Communication Foundation (WCF) integration, declarative authoring and dramatically simplified designer rehosting. 2011 brought a fully featured version of StateMachine in the Microsoft .NET Framework 4 Platform Update 1, available today with the same quality and support guarantees as any other component of the framework. With WF 4.5, our goal was to solve the major issues we learned about from our customers. We’ve also been working to take all the power of WF to the cloud; there’s a great BUILD presentation you can watch to see what the team has been up to (bit.ly/rbJROw).

As you read through this article, I’m sure you’ll have questions about compatibility between WF 4 and WF 4.5. Be assured that the versions are built on the same code base and are fully compatible. All your WF 4 investments will be preserved in WF 4.5 without needing any changes.

After we shipped WF 4, we received a lot of great feedback we used to plan the next release. In WF 4.5, we wanted to address your top concerns and add features to provide the best framework for building workflow applications. Figure 1 shows customer requests and the features created in response to those requests.

Figure 1 Customer Requests and New Features for WF 4.5

Theme Request Feature
Authoring Improvements Expressions in the language of the project C# Expressions
Create workflow services based on an existing contract Contract-First
Add comments to activities in the designer surface Annotations
Use the WF designer more effectively, especially navigating large workflows Auto-connect, Auto-insert, Pan, Tree view, Auto-surround with sequence
Search integration in the workflow designer Search
Break the build when there’s an error in a workflow in the designer Build integration
Create StateMachine workflows StateMachine
Versioning Basic building blocks for a versioning story WorkflowIdentity
Host several versions of a service side by side WFSH versioning support
Update running instances of a workflow to a new definition Dynamic Update
Runtime Enhancements Run my workflows in Partial Trust Partial trust support
Be able to plug my own expressions story Expressions extensibility
Better runtime performance Visual Basic expressions performance enhancements

Notice that the table is organized by themes; I’ll use the same themes in the upcoming sections to present the most important features.

Authoring Improvements

C# Expressions WF 4 lets you write expressions using Visual Basic and, when used in Visual Studio, the expression editor provides all the language services you might expect, such as auto-complete, IntelliSense and so forth. But our WF 4 customers told us they’d rather write C# than Visual Basic, so we added support for C# expressions. Now, if you create a C# project you get C# expressions in your workflow. Don’t worry, though. You still get Visual Basic expressions if you create a Visual Basic project. C# support also comes with all the language services you’d expect, as shown in Figure 2. Notice the IntelliSense box showing second C# overload for string.Format.

C# Expressions in a Workflow
Figure 2 C# Expressions in a Workflow

If you want to try C# expressions, just create a C# Workflow project. You can also open the CSharpExpressions project in the companion code for this article.

Contract-First Service Authoring WF 4 comes with great WCF integration. You can create WCF services leveraging all of the WF capabilities (long-running execution, durable state, declarative authoring and visibility into execution) without writing a single line of code (see “Visual Design of Workflows with WCF and WF 4” at msdn.microsoft.com/magazine/ff646977). When you author a workflow service in WF 4, service contracts are inferred from the workflow definition. When the host starts, it walks through the workflow definition looking for messaging activities, then exposes the corresponding contract (for example, each Receive activity translates to a service operation).

Many customers said they’d prefer to create their workflow services from an existing WCF service contract (the workflow is just one of the possible implementations of that contract), so in WF 4.5 we added support for “contract-first” service authoring. Now you can import a WCF service contract definition in a workflow project and make one or more workflow services implement that contract. This new approach to workflow service authoring doesn’t replace the workflow-first approach.

Contract-first in WF is a two-step process: You add a reference to the contract (a regular WCF service contract) in your project and then implement the contract in your services.

To import the contract, right-click on the project, select the “Import Service Contract” menu item and choose the contract type. Once the contract is imported and the project is built, a set of activities representing each operation is added to the toolbox, as shown in Figure 3.

The Generated Activities Are Added to the Toolbox
Figure 3 The Generated Activities Are Added to the Toolbox

As Figure 4 shows, you can add activities between the Receive and SendReply. These activities represent the body of the operation.

A Simple Service Method That Computes a Value
Figure 4 A Simple Service Method That Computes a Value

The second step is to indicate that a given service implements the contract. To do this, you open the workflow service in the designer and add the contract to the ImplementedContracts collection of the WorkflowService root.

 Once the service implements the contract, the designer will run a new set of validation rules to ensure the service honors the contract. As a result, you’ll see warnings and errors if the contract isn’t fully implemented.

If you want to see contract-first in action, take a look to the ContractFirst project in the companion code. For a hands-on experience follow the steps described in the previous section.

Use the WF designer more effectively The WF visual designer provides a graphic representation of your workflows, making them easier to create and share. The designer is a key feature of WF and is the most used authoring tool. In WF 4.5, we added highly requested features to enable you to be more productive using it.

Annotations In WF 4, the only place you can add text in the designer is the DisplayName section of an activity, which is a one-line text area at the top of the activity. There’s no other way to add non-structured descriptive information to your workflow. However, you wanted to be able to add comments or text in your activity designer to convey more than just the workflow definition (such as adding a description of the behavior of a process step).

In WF 4.5 we added annotations, which enable you to add textual comments and descriptions to activities in the designer. Figure 5 shows a workflow with and without annotations. Notice how you can now add descriptive information to any activity. With annotations, a printout of the designer can fully convey what the workflow is doing.

A Workflow with and Without Annotations
Figure 5 A Workflow with and Without Annotations

You can display annotations as always visible or as a sticky note in the DisplayName bar of an activity.

Annotations are an opt-in feature and have no execution-time impact. They’re added to the workflow XAML file as attached properties, as shown in the following code snippet:

<Activity mc:Ignorable="sap2010" 
  x:Class="DesignerImprovements.Annotations" 
  xmlns="https://schemas.microsoft.com/netfx/2009/xaml/activities"
  xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:sap2010="https://schemas.microsoft.com/netfx/2010/xaml/activities/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Sequence sap2010:Annotation.AnnotationText="This is an example annotation">
    <WriteLine Text="Hello Dev11"/>
  </Sequence>
</Activity>

To see annotations in action, take a look at the attached Annotations project in the companion code. For a hands-on experience, open a WF 4.5 workflow project, add an activity to the designer and select “Add annotation” in the activity’s context menu.

Enhancing Flowchart and StateMachine Designers You asked us to improve aspects of the design experience to make you more productive, particularly with regard to adding new activ­ities to a Flowchart or StateMachine (available through .NET Framework Platform Update 1). We listened.

We added auto-connect, which enables automatically connecting a new activity to an existing activity in the designer. And we added auto-insert, which lets you insert an activity between two existing activities by dropping the new activity on the connecting line. Figure 6 shows these features.

Auto-Connect and Auto-Insert
Figure 6 Auto-Connect and Auto-Insert

To try this, just create a WF project and add a Flowchart or StateMachine. When adding a new activity, you’ll notice dropping targets for auto-connect. After you’ve connected two activities, you can add a third by dropping it on the connecting line.

Large-Workflow Navigation In WF 4, when a workflow is larger than the screen, you move around using the vertical and horizontal scrollbars. You told us that moving around a large workflow this way is painful and limits your productivity.

In WF 4.5 we added panning, which allows moving through the designer canvas using the mouse. You can enable Pan mode by clicking the Pan button in the designer. Panning is available as a general designer feature, so you can use it with any existing activity.

To try panning, open any workflow in the designer, click the Pan button and enjoy panning around!

WF 4.5 also provides a tree view that allows you to visualize the document outline of your workflow. This gives you a very succinct and structured view of your workflow, enabling you to navigate large workflows more easily. When you click an activity in this view, it’s selected in the workflow definition, as shown in Figure 7.

Document Outline View of a Workflow
Figure 7 Document Outline View of a Workflow

To try this feature, open a workflow in the designer, go to the View menu, select Other Windows and choose Document Outline.

Search Integration in the Designer In WF 4 you can use the Visual Studio search when using the WF designer, but search results aren’t integrated with the WF designer. Clicking a search result doesn’t take you to a particular location in a workflow. You made it clear how this affects your productivity and how important it was for us to provide this capability.

In WF 4.5 we integrated the WF designer with Visual Studio search. Now clicking on a search result takes you to an activity in a workflow, even if it’s nested several levels away.

To try this out, create a workflow project and start editing a workflow in the designer. Add some activities and configure their properties. Now, search for a keyword using Visual Studio search. The search results should take you to the activity that matches the keyword.

Auto-Surround with Sequence The WF 4 activity model supports composition at its very core; activities can be composed without restrictions. For example, the Body property of a While activity can be a Sequence, Parallel, Flowchart, StateMachine, WriteLine, Delay or any other existing activity. Often, composite activities have a Body property that accepts just one activity (instead of a set), which can be any other leaf or composite activity.

One of the more common activities for Body is Sequence, especially with control flow activities like While, ForEach and so forth. With these, if you add a single child and then change your mind in favor of a sequence of elements, you need to cut the child in the Body, then add a Sequence to the Body and paste the child. This is tedious and error prone.

In WF 4.5, we added an “auto-surround with Sequence” feature. For example, if you have a While and its Body is a WriteLine, when you drop another activity, a Sequence containing both the existing activity and the new one is automatically created, as illustrated in Figure 8.

Auto-Surround with Sequence
Figure 8 Auto-Surround with Sequence

To try this, follow the steps in Figure 8.

Build Integration In WF 4 you can create a new activity declaratively in the designer. When you do so, you’re actually defining a new type that will be placed in the assembly generated when the project is compiled. However, if you build a WF 4 project and there are errors in the XAML, the build still succeeds though your workflow is not included in the resulting assembly.

In WF 4.5 we fixed this problem. If you build a workflow that has an error, the build will break, as you’d expect.

To implement this solution, we added extensibility to XamlBuildTask so it can be accessed during compilation of XAML activities, breaking the build when a XAML workflow file has errors.

To try this feature, create a new WF application and add an incorrectly configured activity to a workflow. You’ll get a build error. You can also try the ErrorBreaksTheBuild project in the companion code.

State Machine out of the Box StateMachine is a very important control flow activity that didn’t make it to WF 4. That brought tons of feedback about the importance of this activity, so now StateMachine is available in WF 4 after you install the .NET Framework Product Update 1. In WF 4.5, you won’t need to install any update to take advantage of StateMachine—it’s included right out of the box.

To try this feature, create a workflow project and add a StateMachine activity or just open the StateMachine sample project in the companion code for this article.

Versioning Support

WF 4 doesn’t include support for workflow versioning. If you wanted versioning, you had to write everything on your own, often hitting issues that are hard to work around. WF 4.5 includes new features that enable versioning.

WorkflowIdentity In WF 4, the host is responsible for associations between definitions and instances. Once an instance has been persisted and unloaded from memory, the host must provide the right definition to continue the execution of the instance. One big challenge is that there is no information in the persisted instance state that helps the host determine what definition has been used to create the instance. Furthermore, if the host is configured with the wrong definition when loading an instance, the user will get an awkward exception because the error is a side effect of not being able to match the instance state with the definition, rather than a real version mismatch.

WF 4.5 introduces WorkflowIdentity, a new type that refers to a fully configured workflow definition and is part of the instance runtime state. A WorkflowIdentity contains a name (string), a version (System.Version), and a package (string). Name and version are self-explanatory; package is an optional string used for disambiguation. It refers to the container of the workflow definition (assembly name, service URI, or any string of your choice). WorkflowIdentity is the cornerstone for all WF versioning features.

One of the most useful traits of WorkflowIdentity is that it’s a part of the workflow instance state and lives through the entire lifecycle of an activity: It’s saved during persistence, can be queried from the instance store and is emitted with the tracking information for a workflow instance.

Using WorkflowIdentity is easy. The following snippet shows how to use it with WorkflowApplication, our single-instance, single-definition, in-process host (you just have to pass an instance of WorkflowIdentity to the constructor of WorkflowApplication):

WorkflowIdentity identity = new WorkflowIdentity("Sample", new Version(1, 0, 0, 0),
  "MyPackage");
WorkflowApplication application = new WorkflowApplication(new MyActivity(), identityV1);

We just configured the WorkflowApplication with a Workflow­Identity, but we haven’t yet done anything useful. The next code sample shows how to use the identity to detect a version mismatch and to provide an actionable error message. In the event of a version mismatch when trying to load an instance, you’ll get a VersionMismatchException that states the cause of the problem and contains the supplied and expected identities. This information can be used for logging or recovering from the error:

try
{                
  WorkflowIdentity wrongIdentity = new WorkflowIdentity("Sample", new Version(2, 0, 0, 0), 
    "MyPackage");

  WorkflowApplication application = new WorkflowApplication(new WrongActivity(), 
    identityV2);

  application.Load(instanceId);
}
catch (VersionMismatchException ex)
{
  Console.WriteLine("Version Mismatch! {0}", ex.Message); 
  Console.WriteLine("Expected: {0}; Provided: {1}", ex.ExpectedVersion, ex.ActualVersion); 

}

Finally, you can learn the identity of a given workflow instance before loading it from the instance store. To query the identity, you need to get a WorkflowApplicationInstance, a new type introduced in WF 4.5 that represents an instance that has not been associated with a definition. It’s used to retrieve metadata about the instance—in this case, the identity. See bit.ly/ssAYDn for more information.

Note that WorkflowIdentity works not only with WorkflowApplication, but also with WorkflowServiceHost.

If you want to try this feature, open the WorkflowIdentity project in the companion code.

WorkflowServiceHost WorkflowServiceHost (WFSH) is the out-of-box, single-definition, multiple-instances host for workflows provided in WF 4. However, an unfortunate WF 4 limitation is that changes to the workflow definition result in an exception if you try to load a previously persisted instance into the WFSH. This is because the host is unable to run these instances using the new definition (this is the problem we noted in the WorkflowIdentity section). Some customers worked around the lack of built-in versioning support in WF 4 using multiple WFSHs and a WCF routing service as an intermediary between the client app and the workflows. Clients send messages to the router, which routes the messages to the corresponding WFSH configured with the right version of the definition. The downside is that this requires the client application to be version-aware to successfully send messages to a service instance.

In WF 4.5, WFSH has become a multiversion host; you can deploy multiple versions of a workflow service within the same WFSH and it will deliver incoming messages to the correct version. 

The semantics are very simple: New instances start with the latest version of the service, and running instances continue executing with the version used to start them. There are some restrictions on what you can change from one version to the next; you can’t remove service operations (Receives), but you can add new ones (the rules are similar to creating a derived interface in the CLR).

The key enabler for this feature is WorkflowIdentity. To determine the version of a service definition you need to configure its identity. Old versions of the service must be placed in a “supported versions” folder, which is a folder in App_Code with the same name as the workflow service (see Figure 9). Alternatively, old versions can also be loaded explicitly into the WorkflowServiceHost by adding to the SupportedVersions collection prior to opening the host.

WorkflowServiceHost Side-by-Side Versioning
Figure 9 WorkflowServiceHost Side-by-Side Versioning

With this new feature, the router is no longer needed, and client apps don’t have to be version-aware. They just send a message; the usual correlation mechanism resolves it to the right instance and the host uses the corresponding definition (because the persisted instance state contains the identity of the definition needed to load it). XCopy deployment semantics are preserved, so you don’t need to write a single line of code to use it. This feature is also available in self-hosting scenarios (hosting WFSH in your own app).

To try this feature, open the WFSH_SxS project in the companion code.

Dynamic Update In WF 4, once a workflow instance has begun, there’s no supported way to change the definition of the workflow. This is often a problem when programs need to be updated due to bug fixes or changing requirements.

Our enterprise customers were emphatic about the importance of this capability, because they often need to change a particular workflow instance in long-running workflows. For example, suppose a workflow that models an interview process has four interviewers but, given a new company policy, now needs to be changed to add a fifth interviewer. You can’t do that with WF 4.

You can in WF 4.5. Dynamic Update allows you to make changes to a running instance of a workflow to accommodate a new workflow definition. Such changes might be motivated by omissions at design time, bugs in the workflow, or new requirements. Dynamic Update isn’t intended for situations that require wholesale changes, resulting in a workflow that differs significantly from its original design. In that sort of case, you should design a new workflow instead of making changes to a running instance.

Dynamic Update is generally a two-step process: When changing the workflow definition, you also need to create an update map: a structure that contains information about the changes. When the new version is deployed, the map can be used to update running instances to the new definition. Running instances can be updated only when they’re idle and persisted.

Dynamic Update, which is available in both WorkflowApplication and WorkflowServiceHost, is an advanced, complex feature, and it has far more capabilities than I’ve mentioned. It supports updating activities, providing custom update semantics, emitting tracking information and more. It gives you a rich API you can use in your applications to provide update capabilities for your running instances.

Runtime Enhancements

I want to briefly describe some runtime enhancements in WF 4.5.Due to space constraints, I won’t be delving into them with the same level of detail as the other features; these are more scoped and advanced.

Partial Trust WF 4 requires full-trust to execute. WF 4.5 can run in partially trusted AppDomains.

Expressions Extensibility We modified ExpressionTextBox to bind to an object instead of a string. As a result, you can provide your own expression editing experience and you’re not limited to a textual representation. We also exposed fast-path capabilities that can be used with code activities for authoring expression activities with better performance.

Visual Basic Performance Enhancements We significantly improved VisualBasicValue/VisualBasicReference performance by changing their internal implementation.

WF 3 Obsoleted WF 3 types have been marked as obsolete in WF 4.5 assemblies.

Wrapping Up

We took WF 4 and, based on your feedback, made it better. We added much-requested features and fixed some key issues to provide you with the best workflow framework for your .NET applications.

WF 4.5 is an in-place replacement for WF 4 and is fully compatible with WF 4. We have thoroughly tested that WF 4.5 doesn’t break any WF 4 scenarios; all your WF 4 investments will be fully preserved in WF 4.5 without need of any changes.

If you’re writing WF 4 applications, keep doing so! When you’re ready to move to WF 4.5, your code will just work, and you and your customers will be able to leverage and enjoy all the improvements described in this article.


Leon Welicki is a senior program manager on the WF team focusing on the WF programming model and runtime.

Thanks to the following technical experts for reviewing this article: Joe ClancyDave CliffeDan GlickHani Khoshdel Nikkhoo and Isaac Yuen