Book Image

Programming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C#

By : Kenneth Scott Allen
Book Image

Programming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C#

By: Kenneth Scott Allen

Overview of this book

Windows Workflow Foundation (WF) is a technology for defining, executing, and managing workflows. It is part of the .NET Framework 3.0 and will be available natively in the Windows Vista operating system. Windows Workflow Foundation might be the most significant piece of middleware to arrive on the Windows platform since COM+ and the Distributed Transaction Coordinator. The difference is, not every application needs a distributed transaction, but nearly every application does have a workflow encoded inside it. In this book, K Scott Allen, author of renowned .NET articles at www.odetocode.com, provides you with all the information needed to develop successful products with Windows Workflow. From the basics of how Windows Workflow can solve the difficult problems inherent in workflow solutions, through authoring workflows in code, learning about the base activity library in Windows Workflow and the different types of workflow provided, and on to building event-driven workflows using state machines, workflow communications, and finally rules and conditions in Windows Workflow, this book will give you the in-depth information you need. Throughout the book, an example "bug reporting" workflow system is developed, showcasing the technology and techniques used.
Table of Contents (14 chapters)
Programming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C#
Credits
About the Author
About the Reviewer
Preface

Our First Workflow


Maybe you've had one of those product managers who is always at your desk, asking "are you done, yet?" In this section, we will replace the annoying project manager with a trivial Windows Workflow program. The sample isn't meant to demonstrate all the capabilities of the platform, but give a general feel for creating and running a workflow with WF.

Before we can begin, we'll need to download and install the .NET 3.0 framework. The installation program is available from http://netfx3.com. Supported development tools for the .NET 3.0 framework include all editions of Visual Studio 2005. We'll also need to download and install Visual Studio 2005 Extensions for Windows Workflow Foundation. The extensions are also available from http://netfx3.com. The extensions are not compatible with the Express editions of Visual Studio 2005.

First, we'll use Visual Studio to create a new Workflow project (File | New Project). We'll choose C# as our language and select the Sequential Workflow Console Application template (see the screenshot on the next page). The template gives us a project with references to all the correct WF assemblies, an empty workflow, and a Program.cs file to drive the workflow. Right-click the workflow and select Delete so we can start a workflow from scratch.

We can now right-click the project file in the Solution Explorer window and select Add New Item. From the list of items we'll choose Sequential Workflow (with code separation) and give the item the name of workflow1.xoml (see screenshot below). This XOML file will contain the XAML definition of our workflow.

If we click to expand the node containing Workflow1.xoml, we will find a C# code-beside file (Workflow1.xoml.cs) containing a partial class. As we mentioned earlier, the partial class will combine with the class generated from the XAML to produce a single type. Let's modify the class in Workflow1.xoml.cs by adding an IsFixed property with a backing field, as shown below:

public partial class Workflow1 : SequentialWorkflowActivity
{
private bool _isFixed;
public bool IsFixed
{
get { return _isFixed; }
set { _isFixed = value; }
}
}

If we double-click the .xoml file, the designer will appear. At this point we would want to open the Toolbox window if is not open (Ctrl+Alt+X). We can drag a While activity from the Toolbox and drop the activity between the start and end point of our workflow. The While Activity executes a child task until some condition is met. Our next step is to drag a Code activity from the Toolbox into the center of the While activity. At this point, our designer should resemble the following screenshot:

Notice both activities display a red exclamation point. The activities are failing their validation checks. We can hover the mouse cursor over the exclamation points and open a smart tag to view the validation error. If we tried to compile the program we'd see these same validation errors as compilation errors. We'll fix these errors now.

The Code activity requires us to assign an event handler for the ExecuteCode event. We can set the event by opening the Properties window (F4) and clicking the Code activity to set focus. Double-clicking in the empty space beside the ExecuteCode property will send us into the code-beside file and generate a new event handler. We can place the following code into the event handler. This code will ask the user if a bug is fixed, and then read a key press. If the user presses the 'y' key, the code will set the _isFixed field to true.

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Is the bug fixed?");
Char answer = Console.ReadKey().KeyChar;
answer = Char.ToLower(answer);
if (answer == 'y')
{
_isFixed = true;
}
else
{
Console.WriteLine();
Console.WriteLine("Get back to work!");
Console.WriteLine();
}
}

The Code activity should now pass validation, so we can turn our attention to the While activity. A While activity requires a valid Condition property. Several activities in the base activity library work with conditions, including the IfElse, ConditionedActivityGroup, and Replicator activities. Chapter 9 will cover conditions and rules in more detail.

We can set the Condition property of our activity by opening the drop‑down list beside the Condition property in the Properties window. We have the choice of selecting a CodeCondition or a RuleConditionReference. These choices represent the two techniques available to express a condition, the first being with code (a method that returns a Boolean value), the second being with a rule. Let's select the RuleConditionReference. A rule condition is a named expression that evaluates to true or false, and can live in an external .rules file for easy maintenance. A plus sign appears beside the Condition property, and we can click the sign to expand the property editor.

When the Condition property expands, the Property window gives us the ability to set a ConditionName and an Expression. Clicking on the ellipsis (…) button in the Condition name will launch a Select Condition dialog box.

Clicking the New Condition... button will launch the Rule Condition Editor.

We want the While activity to loop until the bug is fixed. Our rule is !this.IsFixed. Once we've entered the condition (notice the editor provides IntelliSense), we can click OK. When we return to the Select Condition dialog box, we can see the editor has given our condition the name of Condition1. We should select Condition1 and press OK. The While activity should now have a ConditionName and Expression set, and pass validation.

Now we need to open the Program.cs file, which contains the method Main—the entry point for our Console application. We need to host the WF runtime and ask the runtime to execute our workflow. The item template for a workflow project provides all the boilerplate code we need. Let's review the code:

class Program
{
static void Main(string[] args)
{
WorkflowRuntime workflowRuntime = new WorkflowRuntime();
workflowRuntime.WorkflowCompleted +=
new EventHandler<WorkflowCompletedEventArgs>
(workflowRuntime_WorkflowCompleted);
workflowRuntime.WorkflowTerminated +=
new EventHandler<WorkflowTerminatedEventArgs>
(workflowRuntime_WorkflowTerminated);
WorkflowInstance instance;
instance = workflowRuntime.CreateWorkflow(typeof(Workflow1));
instance.Start();
waitHandle.WaitOne();
}
static void workflowRuntime_WorkflowTerminated(object sender,
WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
}
static void workflowRuntime_WorkflowCompleted(object sender,
WorkflowCompletedEventArgs e)
{
waitHandle.Set();
}
static AutoResetEvent waitHandle = new AutoResetEvent(false);
}

The first step is to instantiate a WorkflowRuntime instance. The code wires up event handlers to the runtime so we know if a workflow terminates (because of an exception), or completes successfully. The code instantiates our bug-fixing workflow using the CreateWorkflow method, passing the type of our workflow. Since the workflow engine executes our workflow asynchronously, we need to block our thread on an AutoResetEvent object and wait for the workflow to complete (otherwise, the console mode program would exit before the workflow gets an opportunity to run). An AutoResetEvent object will block a thread until the object is in a signaled state, which we do with the Set event in the event handlers.

We can now build our workflow solution and run the executable from the command line.