This article will walk you through building a state machine workflow, which is one of the several workflow types supported by the Microsoft .NET Framework 3.0 and Visual Studio 2005.
Necessary Components and Setup
You will need to have the following components to build the examples contained within this article. I personally downloaded them and set up a .NET Framework 3.0 Virtual PC environment. I’ve found this to be a good practice for trying out new things and for preserving various environments. It is especially handy when you have a particular environment that you need to support every so often that is outside your normal development.
- .NET Framework 3.0 Runtime Components
- Visual Studio 2005 Extensions for .NET Framework 3.0 (Windows Workflow Foundation)
State Machine Workflow
In my article Get Ready for Windows Workflow Foundation, the focus was on sequential workflow, which involves a prescribed processing order that relates closely to a top-down sequential flowchart model. In comparison, a state machine workflow is more flexible and you have more control and visibility in to the state. Whereas a sequential workflow involves a set of activities that are set up to occur in a pre-defined sequence, a state machine workflow models the possible states for a particular entity and specifies events. A set of events can be received for any given state. When events occur, an action is performed; at the end of this action, a state transition may or may not be made. Steps in the workflow can be skipped and/or jump to any step in the workflow. This type of activity is ideal when the exact sequence of events is not well known in advance.
Although a state machine is different in behavior than a sequential workflow, it can use the same activities as a sequential workflow. Thus, actions taken within any particular transition of state can contain sequential activities and other logic, which can allow for a best of both workflow styles to better match processes. There is a base activity library that contains some activities for state machine workflow. They include:
- EventDriven: Defines a transition that is executed when a specific event is received while in a particular state. The transition contains one or more activities to be executed when the specific event is received.
- SetState: Changes the state of the state machine from one state to another.
- State: Represents a particular state in the state machine.
- StateInitialization: Defines one or more activities that that are executed whenever an assigned state is entered.
Building a State Machine Workflow
A state machine workflow is commonly used in scenarios such as the following:
- Human interaction with a process where there are delays in processing or different flow of activities
- Ad hoc transitions within a process as opposed to sequential flow
- Workflow is driven by external events or influencing entities
State machine workflows that very commonly represent business processes as entire processes rarely flow sequentially from beginning to end. Fulfillment of orders through an e-commerce system, new account creation process, and employee on boarding are all example processes that may fit well into a state machine model. For this article, my colleague Rachel has come up with a sample involving choosing your favorite color. This sample will allow you to keep things relatively simple for the purposes of this article. The states for this example are starting, selecting red as your favorite color, selecting blue as your favorite color, and ending the workflow.
Use the following outlined steps to create a state machine workflow within Visual Studio 2005. There are a number of steps to describe as you walk through the example. As with any set of detailed instructions, you may have to read through them carefully a few times to ensure you catch all of the parts.
- Create a new project: For my example, I’m using C#, Workflow, State Machine Workflow Console Application as the project type.
- When you create the workflow project, it will use the workflow definition and code in the same file by default. I deleted it and added a new item, State Machine Workflow (with code separation),. and named it FavColor.xoml. I prefer the code separation for maintainability purposes.
- By default, the state machine workflow will have an StateInitialization activity in the designer, which I deleted for this example. From the Visual Studio Toolbox, you should find a Windows Workflow tab if you have your environment installed properly. Drag four state activities onto the designer. I named them stateActivityStart, stateActivityRed, stateActivityBlue, and stateActivityEnd.
- Click the background on the state workflow designer, right-click, and select properties. In the properties window for the state machine workflow, set the InitialStateName property to stateActivityStart. Set the CompletedStatename property to stateActivityEnd.
- Drag an EventDriven activity from the Toolbox on to the top of the stateActivityStart state and name it something similar to eventDrivenActivityAskForColor.
- Drag an EventDriven activity from the Toolbox on top of the stateActivityRed state in the designer and name it something similar to eventDrivenActivityRed.
- Drag an EventDriven activity from the Toolbox on top of the stateActivityBlue state in the designer and name it something similar to eventDrivenActivityBlue.
- The design canvas should now look similar to the following:
- In the designer canvas, double-click on the eventDrivenActivityAskForColor activity in the stateActivityStart state. The first child activity of an EventDriven activity must implement IEventActivity and states generally handle events. To make this example as simple as possible, however, you will use the Delay activity as the first child of all EventDriven activities with the delay property set to 1 second. Add a Delay activity of this description to the eventDrivenActivityAskForColor activity.
- When you set the ExecuteCode property, Visual Studio will bring you to the handler in the code behind. Add the following code to the handler:
Note: The designer for the state machine is freeform so you can locate states wherever you would like.
private void codeActivityAskFavColor_Execute(object sender, EventArgs e){ Console.Write("Enter 1 for red and 2 for blue: "); string answer = Console.ReadLine(); while (answer != "1" && answer != "2") { Console.Write("Please enter a 1 or 2: "); answer = Console.ReadLine(); } FavColor = answer;}
private string favColor = "";public string FavColor{ get { return favColor; } set { favColor = value; }}
- Add a code activity named codeActivityUserChoseRed and set its ExecuteCode activity to codeActivityUserChoseRed_Execute. Visual Studio will switch to the handler in code behind. Add the following code to the handler:
private void codeActivityUserChoseRed_Execute(object sender, EventArgs e){ Console.WriteLine("You chose red!"); TryAgain = AskToTryAgain();}private bool tryAgain = false;public bool TryAgain{ get { return tryAgain; } set { tryAgain = value; }}private bool AskToTryAgain(){ TryAgain = false; Console.Write("Would you like to try again (y or n)? "); string answer = Console.ReadLine(); while (!answer.Equals("y") && !answer.Equals("n")) { Console.Write("Please enter y or n: "); answer = Console.ReadLine(); } if (answer.Equals("y")) { return true; } else { return false; }}
private void codeActivityUserChoseBlue_Execute(object sender, EventArgs e){ Console.WriteLine("You chose blue!"); TryAgain = AskToTryAgain();}
Console.WriteLine("Workflow finished. Press enter to end.");Console.ReadLine();
Summary
This article covered state machine workflow with Windows Workflow Foundation. Even a simple example can turn lengthy in steps, but hopefully this look at state machine gave you an idea of the power and how it can be used to more closely match business and other processes. Much of the work in this example was done through the designer and configuring and setting properties.
Future Columns
The topic of the next column is yet to be determined. It will likely cover either building custom activities, building a rules-based workflow, or using the StateMachineTracking service to track state in state machine workflows. However, if you have something in particular that you would like to see explained here, you could reach me at mstrawmyer@crowechizek.com.
About the Authors
Mark Strawmyer, MCSD, MCSE, MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in the architecture, design, and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the fourth year in a row. You can reach Mark at mstrawmyer@crowechizek.com.
Rachel Wireman is a developer of applications for large and mid-size organizations. She specializes in development of Smart Client applications. Rachel is with Crowe Chizek in Oak Brook, Illinois and contributed to the examples within the article. You can reach Rachel at rwireman@crowechizek.com.