for input), and a bookmark must be defined to mark the current execution point in the workflow.
Persistence is particularly important when you have long-running workflows, where you want to be
able to unload workflows that are idle and waiting for input, or if the machine/server may restart in
the times that the workflow is idle, or if the execution may even continue on a different server (such
as in a server farm).
Note that the workflow itself is not persisted to the instance, only its state. You
need to be aware of the consequences of modifying the workflow while instances
are still alive and persisted, and cater accordingly.
WF comes with a default persistence provider called SqlWorkflowInstanceStore that handles
persisting a workflow instance to a SQL Server database. You can also create your own custom
persistence provider by inheriting from the InstanceStore class.
You have two ways to persist a workflow instance. One is to use the predefined Persist activity from the
Toolbox in your workflow, which will persist the workflow instance when executed by the run time.
The other option is for the host to register an event handler for the PersistableIdle event, which
is raised by the run time when the workflow instance is idle (but not yet complete). The host can then
choose whether or not to persist the workflow instance, returning a value from the PersistIdleAction
enumeration that will tell the run time what it should do.
tracking
WF enables you to implement tracking in your workflows, where various aspects of the execution
of a workflow can be logged for analysis. Tracking provides transparency over your workflow,
enabling you to see what it has done in the past and its current execution state by the workflow run
time emitting tracking records.
You can specify the granularity at which the tracking records will be emitted by configuring a
tracking profile, which can be defined either in the App.config file or through code. This will
enable you to specify which tracking records you want the workflow run time to emit. The types of
tracking records that can be emitted include workflow life cycle records (such as when a workflow
starts or finishes), activity life cycle records (such as when an activity is scheduled or completes, or
when an error occurs), bookmark resumption records, and custom tracking records (which you can
emit from your custom activities). These tracking records can include associated data, such as the
current values of variables and arguments.
Where tracking records are written is determined by specifying a tracking participant. By default,
the WF run time emits tracking records to the Windows Event Log. You can create your own
Getting started .
707
tracking participants if you, for example, want to write tracking records to a different source,
such as a database.
You can also trace the execution of a workflow for troubleshooting and diagnostic purposes, which
makes use of the standard .NET trace listeners. Tracing can be configured in the App.config file.
GettinG started
Start by opening the New Project dialog and navigating to the Workflow category under your
favorite language (as shown in Figure 32-1).
fiGure 32-1
As you can see, you have four project types to choose from as follows:
.
Activity Designer Library: Enables you to create and maintain a reusable library of activity
designers to customize how their corresponding activities look and behave in the WF
designer.
.
Activity Library: Creates a project that enables you to create and maintain a reusable library
of activities (consisting of other activities) that you can then use in your workflows. Think
of it much like a class library but for workflows.
.
Workflow Console Application: Creates an empty workflow hosted in a console application.
.
WCF Workflow Service Application: Creates a workflow hosted and publicly exposed as a
WCF service.
708 . chaPter 32 WindoWS WorkFloW FoundATion (WF)
For the sample project, you will use the simplest option to get up
and running, by using the Workfl ow Console Application project
template. As you can see from Figure 32 - 2, the project it generates is
very simple, containing Program.cs / Module1.vb and Workflow1
.xaml . The Program class (for C# developers), or Module1 module
(for VB developers), as found in any console application, contains
the entry point for the application (that is, the static/shared Main
method), which is automatically confi gured to instantiate and execute
the workfl ow. The Workflow1.xaml fi le is the fi le where you will
defi ne your workfl ow.
fiGure 32 - 2
You aren ’ t limited to hosting workfl ows in a console application or WCF
service — you can also host them in other platforms such as Windows Forms,
WPF, or ASP.NET applications. Add a workfl ow to an existing project using the
Add New Item dialog and selecting Activity from the Workfl ow category (there is
no Workfl ow item, because a workfl ow is essentially an activity itself, containing
other activities).
Note that the workfl ow fi le is a XAML fi le — a fi le format you may recognize
because it is used to defi ne user interfaces in WPF and Silverlight. However, in
this case it is used to declaratively defi ne a workfl ow. You can view and edit the
underlying XAML for a workfl ow by right - clicking the fi le and selecting View
Code from the context menu.
Before you do anything else, compile and run the application as is to see the result. You should fi nd
that a console window briefl y appears before the application automatically ends (because it is not
currently confi gured to actually do anything).
The name Workflow1.xaml isn ’ t very meaningful, so you will no doubt want to change that to
something more appropriate. Unfortunately Visual Studio doesn ’ t help you much in this respect
(unlike with forms and classes), because changing the fi lename will not automatically change the
class created behind the scenes for the workfl ow, nor will it change any references to the class when
you change its name in the designer. For example, to rename the workfl ow and its corresponding
class to SimpleProcessWorkflow , you will need to:
Change the name of the fi le (in t . he Solution Explorer).
. Change the name of the corresponding class (by clicking the design surface, and assigning
the name to the Name property in the Properties tool window).
. C hange all existing references to the workfl ow class. In this case where you haven ’ t done
anything with your project as yet, the only reference will be in the Program class (for
C# developers) or Module1 module (for VB developers), which will need to be updated
The Workflow foundation Designer .
709
accordingly. Note that the class name will not appear in IntelliSense and will indicate an
error when you enter it, if you have not compiled the project after changing the class name
(because it’s only then that the compiler will regenerate the class).
the workflow foundation desiGner
The WF designer enables you to drop control flow activities and standard activities (from the
Toolbox) on a workflow design surface, and connect them to form the workflow. It’s much like
building a form where you drop controls from the Toolbox onto the design surface, but in this case
you are building a workflow. When you first create the project, the empty workflow is displayed in
the designer, as shown in Figure 32-3.
fiGure 32-3
At the bottom of the designer, you will note the three hyperlink buttons: Variables, Arguments, and
Imports. Clicking one of these buttons pops up a pane at the bottom of the designer that will enable
to you modify their respective configurations.
Variables can be defined for use by activities within a given scope (which is defined by a parent activity
to which the variables are attached). Add a variable by simply popping up the Variables pane (as shown
in Figure 32-4), clicking in the area that says Create Variable, and entering a name for it. You can set
the type for the variable by clicking in the Variable Type column and selecting the type from the drop-
down list. If the type that you need doesn’t appear in the list, you can click the Browse for Types item,
which will pop up a dialog enabling you to type in the qualified name of the type, or navigate through
the referenced assemblies tree to find it. Clicking in the Scope column displays a drop-down list that
will allow you to modify the scope of the variable (by selecting the activity it belongs to). This activity
and its child activities will therefore have access to the variable. Clicking in the Default column enables
you to enter an expression (in VB code) that will set the default value of the variable.
710 . chaPter 32 WindoWS WorkFloW FoundATion (WF)
The Arguments pane (as shown in Figure 32 - 5) enables you to defi ne the input and output
arguments for an activity (which enable the fl ow of data in and out of the activity). There are four
types of arguments (that is, argument directions): Input arguments, Output arguments, In/Out
arguments, and Property arguments.
. Input arguments can conceptually be considered the same as passing parameters into
methods by value in regular code.
. Output arguments can conceptually be considered the same as output parameters in
methods in regular code, whose values are set in the method and returned to the caller.
. In/Out arguments can conceptually be considered the same as passing parameters into
methods by reference in regular code.
. Property arguments can conceptually be considered the same as assigning property values
on an object in regular code.
Add an argument by simply popping up the Arguments pane, clicking in the area that says Create
Argument, and entering a name for it. Specify the type of argument by clicking in the Direction
column and selecting a type from the drop - down list. You can set the type for the argument by
clicking in the Argument Type column and selecting the type from the drop - down list. As with
variables, you can also assign an expression to the default value of the argument (for In and
Property arguments only).
fiGure 32 - 4
Note that the default value column accepts expressions rather than values. If you
want to assign a value to the variable rather than an expression you will need to
enter the literal value, not simply the value itself. The literal values for numeric
values are identical, but if the variable is a string, you will need to enclose it in
double quotes. This also applies when setting the default value of arguments.
Note that activities can also have a return value.
The Workflow foundation Designer .
711
fiGure 32-5
The Imports pane (as shown in Figure 32-6) enables you to import namespaces (the same as defining
using statements in C#) for use in expressions. At the top of the panel is a combo box where you can
type a namespace to import and add to the list, or select a namespace from the drop-down list.
fiGure 32-6
Workflows can become quite large and potentially unwieldy as they increase in complexity, but
luckily the WF designer contains a few tools to help you manage and navigate through the model.
You will find that some activities have an icon in their top-right corner, enabling you to roll them
up to just display their title (that is, collapse them), or to expand them if they are collapsed. Because
you can nest activities within activities (and so on), potentially creating rather deep and complex
hierarchies, it can be useful to hide some of this complexity by collapsing activities when you are
not actively editing them. Collapsing activities can reduce the amount of space they take in the
workflow diagram, and can also be used to hide the complexity of the hierarchy of sub-activities
contained within them. You can then expand the activities again by clicking this same icon (whose
arrows will have changed direction according to the state of the activity).
In the top-right corner of the designer, you will find an Expand All hyperlink button and a Collapse
All hyperlink button (both of which change to read Restore when clicked). It can often be useful to
“roll up” the entire workflow (using the Collapse All hyperlink button) to its top-level activities, from
which you can then drill down through specific activities by expanding them as required to follow a
specific logical path. In addition, you can also use the Expand All hyperlink button to expand all the
activities that form the workflow, enabling you to get a picture of the full extent of the workflow.
You can zoom in and out of the view of the workflow using the drop-down list in the bottom-right
side of the designer (that lists zoom percentages), and clicking the magnifying glass icon to its left
resets the view back to 100%. The icon to the right of the drop-down list will automatically select
712 .
chaPter 32 WindoWS WorkFloW FoundATion (WF)
a zoom level that will enable the entire workflow to be fitted within the visible area of the designer
window (without requiring you to scroll).
When you have a large workflow with activities you don’t want to collapse, with it far too big to
fit entirely in the visible area of the designer window, you can make use of the Overview window by
clicking the rightmost icon in the bottom-right side of the designer. This will pop up a window in
the designer (as shown in Figure 32-7) that enables you to pan around the workflow by clicking
and dragging the orange rectangle (representing the visible portion of the workflow in the designer)
around to display the part of the workflow that you want to currently view.
fiGure 32-7
As previously discussed, one of the advantages of using WF is that the diagram of the workflow can
be used as a form of documentation for your business process/logic/rules. It can often be useful to
place this diagram in documentation or presentations, and the way to do this is quite easy. Right-
click anywhere on the design surface. Two items appear in the context menu that you can use for
this purpose: Save as Image and Copy as Image. Selecting the Copy as Image menu item copies a