Microsoft & .NET.NETState Machine Workflow with WinWF

State Machine Workflow with WinWF

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

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.

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.
  • Note: The designer for the state machine is freeform so you can locate states wherever you would like.

  • 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:
  • 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;}
  • You also will need to add the following field and property to the workflow object:
  • private string favColor = "";public string FavColor{   get { return favColor; }   set { favColor = value; }}
  • Switch back to the designer view and add an IfElse activity below the code activity in the designer canvas.
  • Name the IfElse activity’s left branch ifElseBranchActivityRed. Set the Condition property to “Declarative Rule Condition.” Expand the Condition property and click on the ellipsis. Add a condition and set its body to: this.FavColor.Equals(“1”). Rename it to “ConditionRed”. Add a second condition and set its body to: this.FavColor.Equals(“2”). Rename it to “ConditionBlue”. Select “ConditionRed” and click OK. This is a simple demonstration of allowing you to make a logic decision based on state.
  • Name the IfElse activity’s right branch ifElseBranchActivityBlue. Set the Condition property to “Declarative Rule Condition.” Expand the Condition property and click on the ellipsis. Choose “ConditionBlue” and click OK.
  • Add a SetState activity to both the left and right branches and name them setStateActivityRed and setStateActivityBlue respectively. Set their TargetStateName properties to stateActivityRed and stateActivityBlue respectively.
  • The designer for stateActivityStart should now have the components similar to the following diagram:
  • Return to the designer canvas for the workflow. You will notice there are transition lines that now will appear from the starting state to the red and blue states. These lines are a result of the SetState activities and can be controlled through the designer.
  • Double-click on the eventDrivenActivityRed activity in the stateActivityRed state.
  • Add a delay event using similar steps to what you followed for the last delay event.
  • 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;   }}
  • You will use a similar action for the blue state, so you can go ahead and add the following handler to the code behind for the blue state:
  • private void codeActivityUserChoseBlue_Execute(object sender,                                               EventArgs e){   Console.WriteLine("You chose blue!");   TryAgain = AskToTryAgain();}
  • Switch back to the designer for the red state. Add an IfElse activity below the code activity and name its left branch ifElseBranchActivityTryAgain.
  • Set the Condition property to Declarative Rule, expand the property, and click on the ellipsis. Create a new rule named ConditionTryAgain with a body of this.TryAgain and click OK to set it as the condition for this branch.
  • Add a SetState activity named setStateActivityTryAgain, and set TargetStateName to stateActivityStart. This will cause the workflow to cycle to the beginning state if the user chooses to make his/her favorite color choice again.
  • Name the right branch of the IfElse ifElseBranchActivityEnd. Leave its condition blank causing it to be an else branch. Add a SetState activity named setStateActivityEnd with a TargetStateName of stateActivityEnd. This will cause the workflow to end if the user chooses not to make his/her favorite color choice again.
  • Do the same thing you did for the red state now for the blue state. Be sure to set the execute code property of the blue state Code activity to the codeActivityUserChoseBlue_Execute method you prepared in advance earlier. The stateActivityBlue diagram should look similar to the following:
  • When you compile and run the example, it will run through and flash on the screen. You may want to add the following lines to the end Main in Program.cs to cause the application to pause at the end:
  • Console.WriteLine("Workflow finished.  Press enter to end.");Console.ReadLine();
  • You now should run the state machine workflow and watch it cycle through the different states as you make different choices. I used break points within Visual Studio to be able to step through the logic as it cycles.

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.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories