WF Migration: Best Practices for WF3 Developers Status: Final Draft, .NET 4 Beta 2 Last Modified: 2/9/2016 9:59:30 PM Introduction The audience for this paper is the community of developers using or intending to use the current implementation of Windows Workflow Foundation (WF), a technology that first shipped as part of the .NET Framework 3.0, and includes the types in the System.Workflow.* namespaces. In this paper, we will refer to this technology as WF3. This paper includes guidance and specific best practices that will allow WF3 developers to plan and prepare for migration to the new implementation of WF that is being introduced in .NET 4 (the types in the System.Activities.* namespaces; referred in this paper as WF4). Even if you are not adopting WF4 immediately, there are best practices you can follow which can make eventual migration of WF3 solutions to WF4 easier. Please see the “WF Migration Overview” document for an introduction to WF3 to WF4 migration, and links to related documents. The latest versions of these documents can be found at http://go.microsoft.com/fwlink/?LinkID=153313 The information contained in this document relates to pre-release software product, which may be substantially modified before its first commercial release. Accordingly, the information may not accurately describe or reflect the software product when first commercially released. This document is provided for informational purposes only, and Microsoft makes no warranties, express or implied, with respect to this document or the information contained in it. Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property. Microsoft, Windows, Visual Studio, and the .NET logo are trademarks of the Microsoft group of companies. All other trademarks are property of their respective owners. WF Migration: Best Practices for WF3 Developers (.NET 4 - Beta 2 Release) Page 1 Workflow Best Practices Workflows (compositions of activities) in WF4 are fully declarative. There is no code-beside or code-inline accompanying the definition of a workflow. All execution logic in a WF4 workflow is defined in terms of activities. All data (variables) and argument bindings used by activities in a WF4 workflow are also specified as part of the workflow definition. Please see the “WF Migration Cookbook: Workflows” document for instructions and examples showing how to redesign a WF3 workflow as a WF4 workflow. Best Practices: Workflow Development WF3 Best Practice Explanation [1] Do not use the WF3 CodeActivity. Author custom activities instead. There is no code-beside logic in WF4. All custom logic is packaged as custom activities. [2] Do not use code-beside to author event handlers for activity events (such as DelayActivity’s InitializeTimeoutDuration event). Author custom activities instead, and utilize WF4 activity delegates in order to provide extensibility points to the users of your activities. There is no code-beside logic in WF4. All custom logic is packaged as custom activities. [3] Do not use ActivityBind to directly bind a property of one activity to a property of another activity. Instead, define a variable in your codebeside (yes, this usage of code-beside is ok), and bind activity properties to this variable. In WF4, variables are part of the activity model. For example, the WF4 Sequence activity allows the declaration of one or more variables, which can then be bound to the arguments (inputs and outputs) of activities within the Sequence. Here is an example of a WF3 workflow that uses a CodeActivity to directly set an activity property value. A functionally equivalent workflow which used the DelayActivity’s InitializeTimeoutDuration event instead of a CodeActivity would be similar. Note: this is not a WF3 best practice. THIS IS NOT A BEST PRACTICE ### XAML workflow definition ### <SequentialWorkflowActivity x:Class="WorkflowConsoleApplication1.Workflow3" x:Name="Workflow3" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"> <CodeActivity x:Name="codeActivity1" ExecuteCode="SetTimeout" /> <DelayActivity x:Name="delayActivity1" /> </SequentialWorkflowActivity> WF Migration: Best Practices for WF3 Developers (.NET 4 - Beta 2 Release) Page 2 ### Code-beside logic ### public partial class Workflow3 : SequentialWorkflowActivity { private void SetTimeout(object sender, EventArgs e) { this.delayActivity1.TimeoutDuration = TimeSpan.FromDays(1); } } THIS IS NOT A BEST PRACTICE Here is an example of the same WF3 workflow, now using a custom activity and a code-beside variable to explicitly represent both the generation of data and the storage of that data. ### XAML workflow definition ### <SequentialWorkflowActivity x:Class="WorkflowConsoleApplication1.Workflow4" x:Name="Workflow4" xmlns:ns0="clr-namespace:MyActivities" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"> <ns0:CalculateTimeout x:Name="calculateTimeout1" Timeout="{ActivityBind Workflow4,Path=timeout}" /> <DelayActivity TimeoutDuration="{ActivityBind Workflow4,Path=timeout}" x:Name="delayActivity1" /> </SequentialWorkflowActivity> ### Code-beside logic ### public partial class Workflow4 : SequentialWorkflowActivity { public TimeSpan timeout; } Activity Best Practices Custom activities in WF3 and WF4 are very similar conceptually. However, since WF4 introduces a new API (for example, new base classes for custom activities), you will need to redesign custom activities in order for them to run natively within WF4. Please see the “WF Migration Cookbook: Custom Activities” document for instructions and examples showing how to redesign a WF3 custom activity as a WF4 custom activity. WF Migration: Best Practices for WF3 Developers (.NET 4 - Beta 2 Release) Page 3 Best Practices: Activity Development WF3 Best Practice Explanation [1] Do not override the WF3 Activity.Initialize and Activity.Uninitialize methods. There are no corresponding methods in WF4 (the activity lifecycle does not include initialization and uninitialization phases). The analog of a WorkflowQueue in WF4 is a Bookmark, which can be named using a string. [2] Use a string (as opposed to some other kind of IComparable) to name any WorkflowQueue your activity creates. [3] Do not define custom events that users can handle in code-beside. Instead, utilize WF4 activity delegates in order to provide extensibility points to the users of your activities. There is no code-beside logic in WF4; see Workflow Best Practice [2] above (do not use code-beside to author event handlers for activity events). WF Hosting Best Practices WF4 includes several options for hosting workflows. Please see the .NET 4 SDK and product documentation for the details and examples of these options. Best Practices: Workflow Hosting WF3 Best Practice [1] Use WorkflowInstance.EnqueueOnIdle instead of WorkflowInstance.Enqueue. Explanation The WF4 runtime uses “resume on idle” semantics. WF Migration: Best Practices for WF3 Developers (.NET 4 - Beta 2 Release) Page 4