Author: Morgan Skinner
Editor: Simon Robinson
Reviewer(s): Damien Foggon, Teun Duynstee
Introduction
As a software developer you'll have heard the following many times…
"That's great, but can you make it do xxxx?"
It might have been someone from the Sales team asking if you could extend the processing of an order entity so that they could add in their own pet feature, or someone from Marketing asking for some extra validation of data before it gets to them. Whatever the question it's likely that you'll groan and have to burn more midnight oil in order to provide a solution.
Windows Workflow Foundation (WF) is perfect in these and other scenarios such as line of business applications with long running transactions and document management solutions - indeed I can't envisage any business application not being able to benefit from using WF. It allows you to define a series of actions (known as activities) and hook these together in a series of steps known as a workflow. At runtime, your code executes the workflow and each step is processed as necessary.
Consider one of the examples above - that of extending the processing of an order. Maybe the sales team would like to be emailed if an order comes in on the website that is over a specific amount. With WF you can add in this extra processing declaratively using a simple user interface, instead of having to crack out your compiler and write real code. This could also mean that you might want to let some suitably trained users make changes themselves.
As this is an introductory article there is no example code to install. Future articles on WF will require you to install the workflow runtime and this will be covered in those articles. If you would like to download and install WF there is a link at the end of the article.
Workflow 101
In the introduction I described that there is a business process attached to ordering from your web site. The flowchart shown in Figure 1 shows what might be happening within your application at present.

Figure 1. Flowchart showing processing for large orders
This shows the process that an order might go through when it is received on your website. If the order is over some amount then the sales team might be sent an email asking them to follow up with the customer with some extra deals, whereas if the order value was less than this amount nothing occurred.
Now, the figure above isn't actually a flowchart - it's a screenshot of a workflow that I've defined for this example. Windows Workflow contains a graphical control that displays arbitrarily complex workflows using a flowchart metaphor. Each element on screen is an Activity, and when running a workflow the runtime engine executes activities in turn.
We can represent the workflow shown above in text as follows…
IfElseActivity - CheckAmount
Over1000
FollowUp
Else
{nothing}
The first activity, IfElseActivity has two immediate child activities - Over1000 and Else. These names are ones I have chosen myself. The Over1000 activity contains a rule that checks the amount of the order, and if the rule evaluates to true the FollowUp activity will be called - this rule is evaluated by the IfElse activity which decides which branch to execute. This activity could do whatever you want - send an email to the sales team, phone a pager, log an entry in a database - it's entirely up to you. Once you have hooked a workflow into your business processes, you can then extend this at a later date as necessary. I'll revisit this later - for now I want to explain how to get this workflow to run.
Executing a workflow
Once you have a workflow defined you then need to execute it - this is the job of the workflow runtime. The runtime is loaded into a process (in this case ASP.NET) and you then ask it to execute a workflow for you. The code below shows some example code that could be used to start a workflow…
// Construct the runtime. This is only needed once per process. WorkflowRuntime runtime = new WorkflowRuntime ( ); // Now create an instance of the SalesWF workflow WorkflowInstance instance = runtime.CreateWorkflow ( typeof ( SalesWF ) ) ; // And kick off that instance instance.Start ( );
Here I've created an instance of the workflow runtime and then started a workflow. You only need to create an instance of the workflow runtime once per process, and this would typically be done within the global.asax file for an ASP.NET application.
Then I create an instance of the workflow and execute it using the Start() method. The runtime will then traverse through each activity within the workflow and execute it. Once all activities have completed the entire workflow will be complete.
Now, you might ask, what is a workflow? From the above it would appear that a workflow is a .NET type - given that I'm calling CreateWorkflow( typeof ( SalesWF ) ). That is indeed correct - when I use the Visual Studio editor I'm actually constructing a .NET type that in this instance derives from a class called SequentialWorkflowActivity.
So, as I drag activities around in the designer, what I'm actually doing is creating a .NET class that contains these objects. If you look at what is created by the workflow designer you'll see two C# files, one that contains the definition of the class (in this case a class derived from SequentialWorkflowActivity) and another file that contains the activities you have added to the workflow. This is conceptually similar to how an ASP.NET page is built.
A workflow then is just a set of activities, with the root activity generally being SequentialWorkflowActivity. Each activity implements the Execute() method, so in effect when we run a workflow all we're doing is calling Execute() methods on all appropriate activities in that workflow definition. Obviously there is a little more to it than that but that's given you an idea of how workflows actually work.
When you run a workflow you are effectively creating an instance of a class and executing that. You may well have a number of instances of the same workflow running at the same time - so in our example there might be any number of orders being concurrently processed. To distinguish between workflow instances we use a GUID. You can create this GUID yourself and assign it to the workflow when creating it, or you can let the runtime create the GUID. Either way this is what is used if you want to communicate to a running instance of a workflow; you can access this ID using the InstanceID property of the WorkflowInstance class.
Now I'll discuss some more in-depth information about activities.
Activities
There are a number of activities built into WF, and if these don't suit your needs you can create your own custom activities. I'll describe a few of the standard activities and what they might be used for here, and also describe a little about creating custom activities.
The Code Activity
When you start coding with any new language the most typical thing you'll want to do is write out "Hello World". I'd be breaking with tradition if I were not to do that here so here's the workflow version. In Figure 2 below I have created a simple workflow and used a CodeActivity that will ultimately call Console.WriteLine().

Figure 2. HelloWorld workflow style
When you add a CodeActivity you can then set the ExecuteCode property to the code that is to run. This is shown in the snippet below.
namespace ASPToday
{
public sealed partial class HelloWF : SequentialWorkflowActivity
{
public HelloWF()
{
InitializeComponent();
}
private void HelloWorld_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Hello World!");
}
}
}
Here the HelloWorld_ExecuteCode() method is called when the HelloWorld activity is executed, and that writes the output to the console. The CodeActivity will typically be used to execute arbitrary sections of code. You can accomplish the same thing as the code activity by creating a custom activity and adding code to its Execute method, however for a short snippet of code this activity will provide the desired results and you'll have less code to write. A code activity simply executes an arbitrary section of code - it shouldn't for example branch to another part of the workflow.
The IfElse Activity
In the example earlier in the document I described the IfElseActivity - this provides you with the capability of executing different nodes based on a condition. The condition I used was checking that the sales amount was greater than 1000, but obviously you could use other conditions too. The IfElseActivity is interesting in that you can define any number of branches within it. Each branch apart from the last must have a condition applied to it, so in effect you can emulate the following programming construct using this activity…
if ( firstCondition ) then
firstActivity;
elseif ( secondCondition ) then
secondActivity;
...
else
lastActivity;
The Delay Activity
The delay activity is one of the most useful activities delivered with WF, even though all it does is halt processing for a definable amount of time. Where this is useful is when you need to deal with something outside your control - such as an external system or when dealing with human interaction.
Lets say you are processing an order and find that the user has not completed their address correctly. In this case you might want to email the user to ask for a complete address, but also be able to timeout after say a week and at that point notify someone in the sales team that an order could not be processed.
The delay activity permits you to wait for a period within a workflow, and when that period expires something else can happen. In the workflow shown in Figure 3 I have defined a delay node (called WaitAWeek) which has its duration set to one week.
When this workflow executes, the first activity is used to send a message to the user. The workflow then enters a waiting state which can be exited either by the user updating their address details, or on a timeout after one week. The activity called ‘Wait' in the example below is an instance of the Listen activity - this provides a number of event driven branches that effectively execute in parallel. The first activity on each branch has to be an ‘event drive' activity, meaning it runs asynchronously and awaits some form of input. When an event is raised that satisfies the wait condition, all other branches are terminated and execution continues down the branch on which the event was raised.

Figure 3. How to use the Delay activity
In the case that the user does not update their details, the WaitAWeek activity will expire and the TellSales activity will then execute. Obviously in a real-world situation there might be further processing that occurred on a timeout or on a successful update, but I'm just trying to describe the main concepts in this article rather than show a complete solution.
This scenario brings up another interesting point about workflow - what happens when a workflow is idle? Does it use up system resources? What happens if the system is rebooted? These and other questions are answered later in this article when I cover Workflow Services.
Custom Activities
Whilst there is a set of activities that come with the system, there is also the need to create custom activities. An activity is just a class that derives from System.Workflow.ComponentModel.Activity - typically you'll need to override the Execute() method to get your activity to do something useful, and you may also want to alter the design time behavior of your activity too.
As shown in Figure 3, different types of activity render a specific icon and background color in the visual designer, so you might want to extend your custom activity to do this too. Providing an icon is as simple as adding an attribute to your activity which describes where the icon is stored. Changing the background fill is a little more involved but still relatively easy. You can completely change the rendering behavior for the entire activity if you wish, but usually the inbuilt styles will suffice.
As an example, the IfElse activity is defined as a composite activity, in that it contains two or more child activities. It has a custom designer which renders the diamond on the connecting lines which makes it look more like a decision diamond within a regular flowchart.
At the end of the article I've provided a link to an MSDN article I wrote which provides further guidance about writing custom activities.
Workflow Services
One of the concepts behind WF is that of services. A service is a unit of functionality that is typically provided by the workflow runtime but could also be provided by custom code.
One of the most critical services is the persistence service - this service allows a workflow to be saved and restored at a later date. As an example, consider what might happen when your website shuts down - if a number of workflows were being processed and there was no persistence service, all that work could be lost. In order to save and restore state you need to use a persistence service, and you'll be pleased to hear that there's one in the box - the SqlWorkflowPersistenceService.
This service unsurprisingly stores workflows within a SQL Server database - you can use either SQL Server 2005 or SQL Server 2000. The schema and stored procedures for this service are supplied for you when you install Windows Workflow, and you can then execute these .sql files on your database as appropriate.
When you create an instance of the workflow runtime within your application you'll typically need to setup the services that you'll use. There are two ways of doing this - you can manually create each service and add it to the workflow runtime, or you can place a list of all services required within the application configuration file and let the workflow runtime read these services and construct instances for you.
Services added to the runtime are shared between all workflow instances, so for example each workflow instance will use the same persistence service. As the services that are defined within WF are based on abstract base classes, you can write your own services and replace our inbuilt ones with your own. Say you would like to use Oracle to persist your workflow state to - all you need to do is subclass WorkflowPersistenceService and implement the appropriate methods, create the schema and appropriate stored procedures and then you can persist workflows into Oracle. This is one of the things that makes workflow so useful - all the native services are pluggable and you can swap the Microsoft implementations for your own.
In addition to the persistence service you can also provide custom implementations of any of the following…
- WorkflowSchedulerService - Used to define how workflows are scheduled for execution. There are two inbuilt subclasses, DefaultWorkflowSchedulerService and ManualWorkflowSchedulerService. In the absence of anything else in the configuration file you'll get the default service.
- WorkflowTransactionService - This service provides transactional capabilities to the workflows, and there are two subclasses, DefaultWorkflowTransactionService and SharedConnectionWorkflowTransactionService. The latter can be used if you are storing persistence and tracking data into the same SQL Server database as its performance is better than the default service.
- TrackingService - This provides the ability to record the state of a workflow and the activities within that workflow as they are executed. Again there are two derived classes, SqlTrackingService and TerminationTrackingService. The former records tracking events into a SQLl database, and the latter can be used to record the termination of a workflow into the event log.
- ExternalDataExchangeService - This service is used when communicating between the application hosting the workflow runtime and the workflow instances being hosted. It effectively acts as a proxy between the host and the workflows.
Of all these services the TrackingService is I believe the most important as it allows you to record the execution state of the workflow. Say you want to record when any workflow starts, stops or goes idle. You can do this with the tracking service and another object called a TrackingProfile. This profile describes which events should be recorded -you can explicitly define which workflow events you are interested in logging and the tracking infrastructure will bypass all others. The tracking profile can also contain a list of activities that you wish to track, and goes down to the events on a particular activity. Your profile can therefore be as specific as you want, and as the tracking service is replaceable you can change what is tracked and to where by writing your own service.
One example of where the tracking information is vital is in an example available in the Windows Workflow SDK called the WorkflowMonitor. This example allows you to browse for workflows that are executing (or have executed) and shows which activities were executed by adding a custom glyph to each executed activity. The image in Figure 4 shows a workflow that has already executed. The tick marks show which activities on that workflow have executed.

Figure 4. A workflow displayed in the WorkflowMonitor
The data for this example is read from the tracking database, as it records each activity that has executed. You could extend the abilities of the monitor sample as appropriate to fit your needs, as you can probably see it would be very useful to be able to display all active workflows and drill into these in the manner shown above.
One other thing that the monitor example shows is the ability to host the workflow designer within your own application. Yes, you read that right - you can embed the workflow designer within your own custom application (for example a Windows Forms application) by calling into WF libraries from your code!.
Hosting the Workflow Designer
The workflow designer has been designed to be extensible, and one of the features is that it can be hosted within your own application. Up to this point I've been using Visual Studio to create workflows, however with this ability you could allow your end users to configure their applications with workflow, and they wouldn't need to have a copy of Visual Studio to allow them to do this.
This is, I believe, the killer feature of Windows Workflow. Whilst the rest of the stuff is fantastic, this ability opens up a whole new avenue of application configuration that could only be dreamed of before. You can ship your application with hooks where workflows can be added, and your end users can add whatever nodes they desire into the application.
Furthermore, the editor that you provide can contain as many or as few of the standard workflow activities as you wish to provide - so you could provide just a custom set of activities and not permit users to use any of the standard ones. It's entirely up to you how much configuration you allow your users to do.
One thing I haven't touched on is the format that a workflow is saved as. Thus far I've said that a workflow is a class which is compiled into a library and then executed. If you provide your own designer, does this mean that code is emitted somewhere that matches the workflow designed? What if there was another way - how about XML?
Storing workflows as XML
Sure enough the workflow designers thought of this scenario - storing workflows as XML. A workflow can be represented either as a chunk of code or as a set of XML elements. A workflow persisted as XML could therefore be stored within a database or as a file on disk, and when executed the runtime converts this representation into one than can be executed and then runs it.
So, your custom designer would use XML behind the scenes to define the workflow, store this in a database, and then run the workflow from the XML.
There are some features that are not available when using an XML based workflow (most notably code behind in Code activities), but other than that they are as functional as code workflows and arguably much more portable.
Conclusion
In this article I've scratched the surface of what is available in Windows Workflow. I believe it will revolutionize configurable applications, and provide a host of other benefits to application developers too. Rather than hard-coding various processing steps in an application a developer will now be able to include a workflow for that part of the application, and then permit another user (possibly the end user) to configure the system using a simple graphical workflow designer.
The ability to host the designer in your own applications is superb - as is the ability to replace services used by the runtime with your own.
For further articles on Windows Workflow see the linked articles, and also come back to ASPToday as we'll be running more articles on Workflow soon.

Sep 20, 10:41 am
Its really good… your way of explainning is awersome…. expecting a asp.net app with work flow……