Developing SharePoint 2007 Sequential and State Machine Workflows with Visual Studio 2008

Summary: Learn how to develop sequential workflows and state machine workflows for Microsoft Office SharePoint Server 2007 by using Microsoft Visual Studio 2008. (23 printed pages)

Steve Hansen, Dakota Technology Group, Inc.

September 2008

Applies to: Microsoft Office SharePoint Server 2007, Microsoft Visual Studio 2008

Contents

  • Introduction to SharePoint Workflows

  • Windows Workflow Foundation Overview

  • Developing SharePoint Workflows Using Visual Studio

  • Developing a Sequential Workflow

  • Developing a State Machine Workflow

  • Deploying a Workflow

  • Conclusion

  • About the Author

  • Additional Resources

Introduction to SharePoint Workflows

Over the past decade, many companies have invested in IT solutions that formalize work processes or workflows. A workflow is the sequence of events required to achieve a desired result; a workflow is the means to an end. By formalizing workflows, companies seek to repeat their success. That is, they learn which activities tend to produce a successful result and then build a process that helps ensure the same result.

Microsoft Office SharePoint Server 2007 is increasingly serving as the central nervous system of many companies. Traditionally, Office SharePoint Server has been used as a portal server for corporate intranets. However, as the capabilities of Office SharePoint Server have expanded in breadth and depth, Office SharePoint Server is different things to different people depending on how they are using it. One of the core competencies of Office SharePoint Server is enabling collaboration. The combination of collaboration features with document management features makes Office SharePoint Server a compelling platform for many corporate workflow processes. Recognizing this fact, Microsoft has embedded Windows Workflow Foundation (WF) within Office SharePoint Server to enable workflows to be formalized by using Office SharePoint Server.

Office SharePoint Server 2007 contains several built-in workflow templates that address commonly encountered workflow situations. However, other than the most trivial workflows, workflow processes are a lot like snowflakes—no two ever seem to be alike. When it comes to designing custom workflows, there are two Microsoft tools to choose from: Microsoft Office SharePoint Designer 2007 and Microsoft Visual Studio.

The objective of this article is to provide an overview of how to develop a custom SharePoint workflow by using Microsoft Visual Studio 2008. Before discussing workflow development with Visual Studio, however, it is essential to have a solid understanding of basic workflow terms and methodology.

Windows Workflow Foundation Overview

Office SharePoint Server uses WF to provide workflow capability. WF consists of an activity library, a programming framework, a run-time workflow engine, and run-time services, components, and tools for building workflow-enabled applications. The run-time engine and services components run within a host's application process.

A workflow in WF is defined by the discrete activities that compose it. When you design a workflow in Visual Studio, you drag activities onto the workflow design surface, and then define the relationship between the activities. Everything is an activity. Do you want to execute a bit of code at a specific place in your workflow? Drop a code activity in the appropriate place. Want to send an e-mail message as part of the workflow? Drop a send e-mail activity in the appropriate place. If you compare this process to developing a user control, you notice that the primary difference is one of semantics: Instead of workflow activities, you drop controls or components onto a design surface. Just as user controls have events that you can hook into, workflow activities also have associated events that provide additional hooks for you to use to add programming logic.

Types of Workflows

There are two types of workflows in WF: sequential workflows and state machine workflows. A sequential workflow follows a linear set of tasks. Although sequential workflows may include branching and looping, progress through the workflow moves from start to finish along a predetermined path.

Whereas a sequential workflow involves a set of activities in a predefined sequence, a state machine workflow consists of possible states that a given entity can occupy with activities that should occur for each state. State machines define a set of events that can be received for any given state, and when an event occurs an action is performed. One of the activities that might occur is a transition to a new state. By modeling a set of states instead of a sequence of events, you have much more flexibility to implement a workflow because the workflow does not need to follow a rigid sequence of activities.

Although a state machine uses a different paradigm at a high-level, the behavior of individual states is implemented much like a sequential workflow. That is, within an individual state—more specifically, within an event associated with a given state—you use the same activities that make up a sequential workflow. After you understand the paradigm of a state machine, implementing the states "feels" much like developing a sequential workflow.

Developing SharePoint Workflows Using Visual Studio

Visual Studio 2008 with Visual Studio Tools for Office simplifies workflow development by including two workflow project templates: SharePoint 2007 Sequential Workflow and SharePoint 2007 State Machine Workflow. The Sequential Workflow template is intended for workflows that follow a predetermined set of tasks. These workflows might involve branching or looping; however, they involve following a sequential flow or progress through the activities that make up the workflow. A simple document review process is a good example of a sequential workflow.

The State Machine Workflow template is intended for workflows that move between states and never follow a specific sequence of activities. For example, consider a workflow that concerns bug resolution. You can think of a bug's status at any given time as its state. During its lifetime, a bug's status can iterate through several states. While it is possible that some bugs are resolved in a sequential manner, there are other occasions where the resolution is much more random, if there is a resolution at all. For workflows such as these, consider using the state machine model.

Glancing ahead in this article, you might be overwhelmed by the number of steps each workflow procedure includes. Don't worry; the steps are easy and there is much repetition. A significant amount of workflow work is "mouse" work, that is, you complete activities through simple mouse clicks and keyboard entry, such as arranging items on a design surface and then configuring object properties.

Developing a Sequential Workflow

Conceptually, sequential workflows are easier to understand than state machine workflows. The following steps walk you through the tasks involved in building a sequential workflow—in this case, a simple document review workflow. This document review workflow watches for new items in a document library, and begins automatically when a new item is added to the document library. When the workflow is initiated, it automatically creates a technical edit task in a task list that is associated with the workflow. After the technical edit is complete, the workflow creates an editorial review task in the task list. When the editorial review is complete, the workflow terminates.

Creating the Initial Project

The following steps show how to create the workflow project and set the workflow's general attributes. The attributes you set include the SharePoint site and the document library that the workflow will be associated with, and how a new workflow starts.

To create the initial project

  1. Open Visual Studio and create a new project.

  2. Select the Office project type node, and then click the SharePoint 2007 Sequential Workflow template.

  3. Name the project SimpleSequentialDocumentReview, and then click OK.

  4. In the first New Office SharePoint Workflow dialog box, provide a user-friendly name for the workflow (for example, Simple Document Review), and then provide a valid SharePoint site URL to use for debugging the workflow.

    Figure 1. Name the workflow and specify a SharePoint site to use for debugging

    Specify a SharePoint site for debugging

  5. In the second New Office SharePoint Workflow dialog box, select the library, history list, and task list that Visual Studio will associate with your workflow when debugging.

    Figure 2. Choose lists or libraries to use for workflow association, history, and tasks

    Lists and libraries to use for workflow

  6. In the final New Office SharePoint Workflow dialog box, accept the default settings, and then click Finish.

    Figure 3. Indicate how the workflow can be started

    Indicate how the workflow can be started

    If you make a mistake or change your mind about the initial settings, you can access the initial workflow dialog boxes to make changes at any time by selecting the project in Solution Explorer, and then clicking the ellipsis in the TargetSite property (some of the other properties also exhibit this behavior).

    Figure 4. Initial view of a sequential workflow project

    Initial view of a sequential workflow project

Visually Designing the Workflow

To design a workflow, drag activities from the SharePoint Workflow and Windows Workflow v3.0 tabs in the Toolbox to the designer work surface. For the simple document workflow, you will use a couple CreateTask activities, a couple OnTaskChanged activities, and a couple While activities. To lay out the simple sequential document review workflow, perform the following steps.

To design a workflow

  1. In the Toolbox, do the following:

    1. Drag a CreateTask activity from the SharePoint Workflow tab onto the design surface directly under the OnWorkflowActivated1 activity.

    2. Drag a While activity from the Windows Workflow v3.0 tab onto the design surface, under the CreateTask1 activity.

    3. Drag an OnTaskChanged activity to within WhileActivity1, on top of the text that reads Drop an Activity Here.

    4. Drag another CreateTask activity to under (not inside of) WhileActivity1.

    5. Drag another While activity to under CreateTask2.

    6. Drag another OnTaskChanged activity into WhileActivity2.

      Figure 5. Simple sequential workflow after laying out workflow activities

      Sequential workflow after laying out activities

  2. Set the properties that are associated with CreateTask1, as follows:

    1. Select the CreateTask1 activity, and rename it CreateTechReviewTask.

    2. Create a task correlation token by entering TechReviewToken in the CorrelationToken property; a PLUS SIGN (+) appears next to the CorrelationToken property. Click the PLUS SIGN to view the OwnerActivityName property and set this property to Workflow1.

      Note

      Correlation tokens are explained after this sequence of instructions.

    3. Click the ellipsis in the TaskId property.

    4. On the Bind to a new member tab, click Create Field, and then click OK. (Note the name of the new field.)

    5. Click the ellipsis in the TaskProperties property.

    6. On the Bind to a new member tab, click Create Field, and then click OK. (Note the name of the new field.)

  3. Set the properties that are associated with CreateTask2 by repeating steps 2a–e, with the following exceptions:

    1. Rename CreateTask2 to CreateEditorialReviewTask.

    2. Create a correlation token named EditorialReviewToken in the CorrelationToken property.

    3. Set the OwnerActivityName property to Workflow1.

  4. Set the properties that are associated with OnTaskChanged1, as follows:

    1. Select OnTaskChanged1, and then rename it OnTechReviewTaskChanged.

    2. Set the CorrelationToken property to TechReviewToken.

    3. Bind the AfterProperties property field to a new field (similar to steps 2e–f).

  5. Set the properties associated with onTaskChanged2.

    1. Select OnTaskChanged2, and then rename it OnEditorialReviewTaskChanged.

    2. Set the CorrelationToken property to EditorialReviewToken.

    3. Bind the AfterProperties property field to a new field (similar to steps 2e–f).

Correlation tokens are an important concept associated with developing workflows. Correlation tokens are used to group associated, related activities in an activity. Correlation tokens are important to understand because if you do not assign correlation tokens correctly, your workflow might not work as you expect. Specifically, events associated with activities might not receive event notifications. By default, a workflow token is created as part of creating a workflow project. You should also create a new token for each task that is created as part of a workflow. Then, for each activity associated with a given task, set the correlation token equal to the correlation token associated with the task.

Another important concept associated with the previous steps is that of BeforeProperties, AfterProperties, and TaskProperties. TaskProperties is a property of a CreateTask activity. BeforeProperties and AfterProperties are properties used by an OnTaskChanged activity. All of these items are Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties objects. An SPWorkflowTaskProperties object contains properties and methods that enable you to affect the fields associated with a given task item. For example, by using an SPWorkflowTaskProperties object, you can assign the task to someone, set the due date, or determine the percent complete. BeforeProperties, AfterProperties, and TaskProperties are all point-in-time objects. That is, the values do not change as the task changes. For an OnTaskChanged activity, BeforeProperties represent the state of a task item before changes were made; AfterProperties represent the state of the task item after the changes were made. For a CreateTask activity, TaskProperties provides you with a way to set the initial properties of the task item when it is created. This is demonstrated later in this article.

Creating Task Items

Although you can set some of the properties of a CreateTask activity by using the designer, it is likely that many of the actual values used to set up the task need to be determined programmatically. To do this, associate an event handler with the CreateTask activity.

To associate an event handler with the CreateTask activity

  1. Select the createTechReviewTask and view the events associated with the activity in the Properties window.

  2. Double-click the MethodInvoking handler to generate an event handler stub that will respond to the MethodInvoking event that occurs before the activity is executed.

  3. Add the following code to the event handler to set the task identifier for the task, and set the due date for the following day.

    createTechReviewTask_TaskId1 = Guid.NewGuid()
    createTechReviewTask_TaskProperties1.DueDate = Date.Now.AddDays(1.0)
    createTechReviewTask_TaskProperties1.Title = "Perform Tech Review"
    
  4. Perform the same steps for the createEditorialReview activity, but add the following code to the event handler.

    createEditorialReviewTask_TaskId1 = Guid.NewGuid()
    createEditorialReviewTask_TaskProperties1.DueDate = Date.Now.AddDays(1.0)
    createEditorialReviewTask_TaskProperties1.Title = "Perform Editorial Review"
    

Waiting for Tasks to Complete

In task-based workflows such as the simple document review workflow discussed in this article, While activities are used to implement the loop needed to watch for task-changed activities, and to see whether a task was marked as complete. To use a While activity, drag a While activity onto the design surface, and then drag any activities that you want to execute repetitively until the While activity terminates and drop them in the While activity.

There are two methods for terminating a While activity: using a code condition or using a declarative rule condition. To use a code condition, add a procedure to the project that sets a Boolean result flag to true or false. To use a declarative rule condition, add a rule to the project. In each pass through the While activity, the rule is evaluated to determine whether the terminating condition was met.

To show how to use both methods for terminating a While activity, we use a code condition for the While activity that is associated with the technical review task and a declarative rule condition for the While activity associated with the editorial review task.

To terminate a While activity

  1. Implement the terminating condition of whileActivity1, as follows:

    1. Switch to the code view and add the following code to Workflow1.vb.

      Private bTaskNotFinished As Boolean = True
      
          Private Sub TaskNotFinished(ByVal sender As System.Object, _
                                     ByVal e As _
                                     System.Workflow.Activities.ConditionalEventArgs)
      
              e.Result = bTaskNotFinished
      
          End Sub
      
    2. Switch back to the workflow designer and select the onTechReviewTaskChanged activity.

    3. Click the Events button in the Properties window to see the events that are associated with onTechReviewTaskChanged.

    4. Double-click the Invoked event to generate a handler for it.

    5. Add the following code to the onTechReviewTaskChanged_Invoked handler.

      If onTechReviewTaskChanged_AfterProperties1.PercentComplete = 1.0 Then _
                  bTaskNotFinished = False
      
    6. Switch back to the workflow designer, and then select the whileActivity1 activity.

    7. Set the Condition property to Code Condition.

    8. Click the PLUS SIGN (+) , and then set the subsequent Condition property to TaskNotFinished.

  2. Implement the terminating condition of whileActivity2, as follows:

    1. Select the onEditorialReviewTaskChanged activity in the designer, and then generate an event handler for the Invoked event.

    2. Add a class-level Boolean variable named bEditorialTaskNotFinished to the class.

          Private bEditorialTaskNotFinished As Boolean = True
      
    3. Add the following code to the onEditorialReviewTaskChanged_Invoked event handler.

        If onEditorialReviewTaskChanged_AfterProperties1.PercentComplete = 1.0 Then _ bEditorialTaskNotFinished = False
      
    4. Switch back to the workflow designer, and then select the whileActivity2 activity.

    5. Set the Condition property to Declarative Rule Condition.

    6. Expand the Condition property.

    7. Click the ellipsis in the ConditionName property to open the Select Condition dialog box.

      Figure 6. Use the Select Condition dialog box to create declarative rule conditions

      Select Condition dialog box

    8. Click New, enter the condition shown in the following figure, and then click OK.

      Figure 7. Example of a declarative rule condition

      Example of a declarative rule condition

    9. Click OK in the Select Condition dialog box.

      Figure 8. Successfully created declarative rule condition

      Successfully created declarative rule condition

Debugging the Workflow

Debugging SharePoint workflows is a particularly satisfying experience with Visual Studio 2008 versus previous versions, in which the debugging process was manual. After compiling, you had to deploy the workflow manually, recycle Microsoft Internet Information Services (IIS), attach the Visual Studio debugger to the W3WP process, open Internet Explorer, navigate to the correct document library, and associate the workflow with the library. With Visual Studio 2008, you simply press F5 and Visual Studio handles all of that for you. All you need to do is trigger a new instance of the workflow by adding an item to the list that the workflow is associated with (assuming you set up the workflow to start automatically when new items are added).

There is one thing to note about debugging workflows. Because you will be looking at Internet Explorer often while debugging the workflow, it is tempting to close the Internet Explorer window when you are finished debugging. But instead of closing the Internet Explorer window, it is best to stop debugging from Visual Studio. When you stop the debugging process, Visual Studio closes the Internet Explorer window for you.

Developing a State Machine Workflow

Now that you have experienced success with a sequential workflow, let's move on to a state machine workflow. To help show the differences between a sequential workflow and a state machine workflow, you will build a workflow to handle the same document publishing process discussed previously in the sequential workflow section. However, state machine workflows require a different approach to thinking about a problem. Instead of focusing on the flow or sequence of events, modeling state machines requires you to think about the states an object can assume during the process.

In the document publishing process, the object of interest is a document. For a simple example, assume that the document can be in the following states:

  • In Progress: State of the document whenever it is actively being worked on by the author.

  • Technical Review: State of the document during the time it is being reviewed for technical accuracy.

  • Editorial Review: State of the document during the time it is being reviewed from a grammatical perspective.

  • Finished: State of the document after it has passed technical and editorial reviews.

A state machine always has an initial state and a completed state.

Creating the Initial State Machine Project

The first set of steps addresses creating the workflow project and setting the general attributes of the workflow such as the SharePoint site and document library it will be associated with, and how a new workflow is started.

To create the workflow project and set general attributes

  1. Open Visual Studio and create a new project.

  2. Select the Office project type node, and then select the SharePoint 2007 State Machine Workflow template.

  3. Name the project SimpleStateMachineDocumentReview, and then click OK.

  4. In the first New Office SharePoint Workflow dialog box, provide a user-friendly name for the workflow (such as Simple Document Review), and then provide a valid SharePoint site URL to use for debugging the workflow.

  5. In the second New Office SharePoint Workflow dialog box, select the library, history list, and task list that Visual Studio will associate your workflow with when debugging.

  6. In the final New Office SharePoint Workflow dialog box, accept the default settings, and then click Finish.

If you make a mistake or change your mind about the initial settings, you can access the initial workflow dialog boxes to make changes at any time by selecting the project in Solution Explorer, and then clicking the ellipsis when you click in the TargetSite property (some of the other properties also exhibit this same behavior).

Figure 9. Initial view and settings of a state machine project

Initial view and settings of state machine project

Adding States to a State Machine Workflow

The next task is to add states to the workflow. This is simply a matter of dragging State objects from the Windows Workflow v3.0 tab in the Toolbox onto the design surface and naming them appropriately. This is also a good time to flag which state represents the completed state.

To add states to the workflow

  1. Select the existing state named Workflow1InitialState, and then rename it stateInProgress.

  2. In the Toolbox, do the following:

    1. Drag a State object to the design surface. Name the state stateTechReview.

    2. Drag a State object to the design surface. Name the state stateEditReview.

    3. Drag a State object to the design surface. Name the state stateComplete.

    4. Flag stateComplete as the completed state by right-clicking it, and then clicking Set as Completed State.

      Figure 10. States in a simple document review state machine

      States in a simple document review state machine

Adding Event-Driven Activities to State Machine Workflows

Event-driven activities are the lifeblood of a state machine workflow. An event-driven activity is a specific event that a given state reacts to. A state can, and often does, have multiple event-driven activities associated with it. In addition to event-driven activities, there are events associated with state initialization and state finalization that you can use to implement logic.

Within an event-driven activity, you build workflows that resemble sequential workflows. You can think of a state machine as a collection of sequential workflows where you define the relationship between the sequential workflows. You define the relationship by using SetState activities within an event-driven activity to transition from one state to another.

To add event-driven activities to a state machine workflow

  1. Right-click stateInProgress, and then click Add StateInitialization. Visual Studio adds a state initialization activity, and opens the designer for the activity. You can return to the state view of the workflow by clicking Workflow1 in the upper-left corner of the design surface.

    Figure 11. Adding activities to the state initialization activity

    Adding activities to state initialization activity

  2. Add a CreateTask activity to stateInitializationActivity1, as follows:

    1. Drag a CreateTask activity from the SharePoint Workflow tab in the Toolbox, and drop it in stateInitializationActivity1. Name the task CreateInProgressTask.

    2. Create a correlation token by entering InProgressToken in the CorrelationToken property for CreateInProgressTask.

    3. Expand the CorrelationToken property, and set OwnerActivityName to stateInProgress.

    4. Click the ellipsis in the TaskId property.

    5. On the Bind to a new member tab, click Create Field, and then click OK.

    6. Click the ellipsis in the TaskProperties property.

    7. On the Bind to a new member tab, click Create Field, and then click OK.

    8. View the events associated with CreateInProgressTask, and then double-click in the MethodInvoking event to generate an event handler.

    9. Add the following code to this event handler.

      CreateInProgressTask_TaskId1 = Guid.NewGuid()
      CreateInProgressTask_TaskProperties1.Title = "Finish document changes/updates"
      CreateInProgressTask_TaskProperties1.DueDate = Date.Now.AddDays(1.0)
      
  3. Add an event-driven activity to stateInProgress to determine when to transition to a new state, as follows:

    1. Switch to the design view of the workflow.

    2. Go back to the state view of the workflow by clicking on Workflow1 in the upper-left corner of the design surface.

    3. Right-click stateInProgress, and then click Add EventDriven.

    4. Rename the newly added event-driven activity eventOnTaskChanged.

    5. Drag an OnTaskChanged activity from the Toolbox, and drop it in eventOnTaskChanged. Name it onInProgressTaskChanged.

    6. Set the CorrelationToken property to InProgressToken.

    7. Click the ellipsis in the TaskId property, and then bind this field to the existing member CreateInProgressTask_TaskId1.

    8. Click the ellipsis in the AfterProperties property, and bind this field to a new field (similar to steps 2f–g).

State machines work a little differently from the sequential workflow described earlier. The sequential workflow used an OnTaskChanged activity within a While activity to repeatedly check the PercentComplete field to see whether the task was complete and the workflow should move on to the next step. A state machine operates by using an event-driven paradigm, so a While activity is not needed. Every time the task changes, the eventOnTaskChanged sequence of activities is executed. In this example, if the in-progress task is marked as complete, the state should transition from in-progress to technical review. To do this, we use an IfElse activity and investigate the value of the PercentComplete field. We access the PercentComplete field by using the AfterProperties associated with the onInPrgressTaskChanged activity.

To transition the state from in-progress to technical review

  1. Determine if a state transition is necessary, as follows:

    1. Drag an IfElse activity from the Toolbox to the design surface, under the onInProgressTaskChanged activity.

    2. Select ifElseBranchActivity1, and then rename it ifInProgressTaskComplete.

    3. Set the Condition property to Declarative Rule Condition.

    4. Expand the Condition property.

    5. Click the ellipsis in the ConditionName property, click New, and then add a rule as shown in the following figure.

      Figure 12. Declarative rule condition for determining whether a task is completed

      Declarative rule condition

    6. Click OK to close the Rule Condition Editor, and then click OK to close the Select Condition dialog box.

    7. Drag a SetState activity from the Windows Workflow v3.0 tab in the Toolbox into the ifInProgressTaskComplete branch. Name it setStateTechReview.

    8. Set the TargetStateName property to stateTechReview.

      Figure 13. Completed event-driven activity for the in-progress state

      Event-driven activity for in-progress state

      After completing the stateInProgress event-driven activity, when you switch back to the state view, you can see that Visual Studio has drawn a line between the in-progress state and the technical review state. This line indicates a relationship between the states—specifically that stateInProgress is capable of transitioning to stateTechReview. One more thing to notice is eventDrivenActivity1, which was created by default. Because stateInProgress is the initial state, eventDrivenActivity1 is an activity that Visual Studio adds that handles the event associated with workflow activation. This example, however, does not need to implement any logic on workflow activation.

      Figure 14. SetState activity causes Visual Studio to display relationships between states in design view

      Relationships between states in design view

  2. Right-click stateTechReview, and then click Add StateInitialization.

  3. Add a CreateTask activity to stateInitializationActivity2, as follows:

    1. Drag a CreateTask activity from the SharePoint Workflow tab in the Toolbox into stateInitializationActivity2. Name the task CreateTechReviewTask.

    2. Create a correlation token by entering TechReviewToken in the CorrelationToken property for CreateTechReviewTask.

    3. Expand the CorrelationToken property, and then set the OwnerActivityName to stateTechReview.

    4. Click the ellipsis in the TaskId property.

    5. On the Bind to a new member tab, click Create Field, and then click OK.

    6. Click the ellipsis in the TaskProperties property.

    7. On the Bind to a new member tab, click Create Field, and then click OK.

    8. View the events associated with CreateTechReviewTask, and then double-click in the MethodInvoking event to generate a handler for it.

    9. Add the following code to this event handler.

      CreateTechReviewTask_TaskId1 = Guid.NewGuid()
      CreateTechReviewTask_TaskProperties1.Title = "Perform Technical Review"
      CreateTechReviewTask_TaskProperties1.DueDate = Date.Now.AddDays(1.0)
      
  4. Right-click stateEditReview, and then click Add StateInitialization.

  5. Add a CreateTask activity to stateInitializationActivity3, as follows:

    1. Drag a CreateTask activity from the SharePoint Workflow tab in the Toolbox into stateInitializationActivity3. Name the task CreateEditReviewTask.

    2. Create a correlation token by entering EditReviewToken in the CorrelationToken property for CreateEditReviewTask.

    3. Expand the CorrelationToken property, and then set OwnerActivityName to stateEditReview.

    4. Click the ellipsis in the TaskId property.

    5. On the Bind to a new member tab, click Create Field, and then click OK.

    6. Click the ellipsis in the TaskProperties property.

    7. On the Bind to a new member tab, click Create Field, and then click OK.

    8. View the events associated with CreateEditReviewTask, and then double-click in the MethodInvoking event to generate a handler for it.

    9. Add the following code to this event handler.

      CreateEditReviewTask_TaskId1 = Guid.NewGuid()
      CreateEditReviewTask_TaskProperties1.Title = "Perform Editorial Review"
      CreateEditReviewTask_TaskProperties1.DueDate = Date.Now.AddDays(1.0)
      

At this stage in the example, all that is left to do is to add event-driven activities to the technical review and editorial review states. For the technical review state, an event-driven activity is needed to watch for changes to the technical review task. If the task is marked as "100% complete", then a decision needs to be made about the state to transition the workflow to. To keep things simple, let's use the Description field associated with the task item. If the text in the Description field is equal to Passed Tech Review, the state will transition to the Editorial Review state, otherwise the state will be moved back to the In Progress state. For the Editorial Review state, we use the same methodology except the state will be transitioned to the in-progress state or the completed state, depending on the value of the Description field. Obviously, a real-world state machine workflow has more complicated logic and more possible state transitions; however, the implementation mechanics are the same.

To add event-driven activities to the technical review and editorial review states

  1. Add an event-driven activity to the technical review state (stateTechReview), as follows:

    1. Go back to the state view of the workflow.

    2. Right-click stateTechReview, and then click Add EventDriven.

    3. Rename the newly added event-driven activity eventOnTechReviewTaskChanged.

    4. Drag an OnTaskChanged activity from the Toolbox into eventOnTechReviewTaskChanged. Name it onTechReviewTaskChanged.

    5. Set the CorrelationToken to TechReviewToken.

    6. Click the ellipsis in the TaskId property, and then bind this field to the existing member CreateTechReviewTask_TaskId1.

    7. Click the ellipsis in the AfterProperties property, and then bind this field to a new field.

  2. Determine whether the Review Task is complete, as follows:

    1. Drag an IfElse activity from the Toolbox to under the onTechReviewTaskChanged activity.

    2. Select ifElseBranchActivity1, and then rename it ifTechReviewTaskComplete.

    3. Set the Condition property to Declarative Rule Condition.

    4. Expand the Condition property, and then click the ellipsis in the ConditionName property.

    5. Select New, and then add a rule with the condition me.onTechReviewTaskChanged_AfterProperties1.PercentComplete = 1.0.

    6. Click OK to close the Rule Condition Editor, and then click OK to close the Select Condition dialog box.

  3. If the task is complete, determine the workflow's new state, as follows:

    1. Drag an IfElse activity from the Toolbox into the ifTechReviewTaskComplete branch.

    2. Rename the left ifElse branch ifTechReviewSuccess. Rename the right ifElse branch ifTechReviewFailed.

    3. Select ifTechReviewSuccess, and then set the Condition property to Declarative Rule Condition.

    4. Expand the Condition property, and then click the ellipsis in the ConditionName property.

    5. Select New, and then add a rule with the condition me.onTechReviewTaskChanged_AfterProperties1.Description="<DIV>Approved</DIV>".

    6. Click OK to close the Rule Condition Editor, and then click OK to close the Select Condition dialog box.

    7. Drag a SetState activity from the Windows Workflow v3.0 tab in the Toolbox into the ifTechReviewSuccess branch.

    8. Name the set state activity setStateEditReview.

    9. Set the TargetStateName property to stateEditReview.

    10. Drag a SetState activity from the Toolbox into the ifTechReviewFailed branch.

    11. Name the set state activity setStateInProgress.

    12. Set the TargetStateName property to stateInProgress.

      Figure 15. Structure of the event-driven activity for the technical review state

      Event-driven activity for tech review state

  4. Add an event-driven activity to the editorial review state (stateEditReview), as follows:

    1. Go back to the state view of the workflow, right-click stateEditReview, and then click Add EventDriven.

    2. Rename the newly added event-driven activity eventOnEditReviewTaskChanged.

    3. Drag an OnTaskChanged activity from the Toolbox into eventOnEditReviewTaskChanged. Name it onEditReviewTaskChanged.

    4. Set CorrelationToken to EditReviewToken.

    5. Click the ellipsis in the TaskId property, and then bind this field to the existing member CreateEditReviewTask_TaskId1.

    6. Click the ellipsis in the AfterProperties property, and then bind this field to a new field.

  5. Determine whether the review task is complete, as follows:

    1. Drag an IfElse activity from the Toolbox to under the onEditReviewTaskChanged activity.

    2. Select ifElseBranchActivity1, and then name it ifEditReviewTaskComplete.

    3. Set the Condition property to Declarative Rule Condition.

    4. Expand the Condition property, and then click the ellipsis in the ConditionName property.

    5. Select New, and then add a rule with the condition me.onEditReviewTaskChanged_AfterProperties1.PercentComplete = 1.0.

    6. Click OK to close the Rule Condition Editor, and then click OK to close the Select Condition dialog box.

  6. If the task is complete, determine the workflow's new state, as follows:

    1. Drag an IfElse activity from the Toolbox into the ifEditReviewTaskComplete branch.

    2. Rename the left ifElse branch ifEditReviewSuccess. Rename the right ifElse branch ifEditReviewFailed.

    3. Select ifEditReviewSuccess, and then set the Condition property to Declarative Rule Condition.

    4. Expand the Condition property, and then click the ellipsis in the ConditionName property.

    5. Select New, and then add a rule with the condition me.onEditReviewTaskChanged_AfterProperties1.Description="<DIV>Approved</DIV>".

    6. Click OK to close the Rule Condition Editor, and then click OK to close the Select Condition dialog box.

    7. Drag a SetState activity from the Windows Workflow v3.0 tab in the Toolbox into the ifEditReviewSuccess branch.

    8. Name the set state activity setStateCompleted.

    9. Set the TargetStateName property to stateCompleted.

    10. Drag a SetState activity from the Toolbox into the ifEditReviewFailed branch.

    11. Name the set state activity setStateInProgress2.

    12. Set the TargetStateName property to stateInProgress.

  7. Return to the state view of the workflow.

    Figure 16. Workflow designer after completing the simple document state machine

    Document state machine in workflow designer

There are many more steps to implementing a document review workflow with a state machine instead of a sequential workflow, but the state machine gives you a lot more flexibility. Although a document review workflow would not normally involve more than a few iterations between technical review, editorial review, and in progress, the fact is that the number of iterations is not known ahead of time. A state machine is an elegant way to handle this because it does not make any assumptions about the sequence of events. You could come close to simulating this in a sequential workflow but it would involve a convoluted set of nested looping and branching activities that would be hard to follow.

Figure17. Tasks created and completed over the life of an example workflow

Example workflow created and completed tasks

Deploying a Workflow

After you develop and debug your workflow, it is likely that you will need to deploy the workflow to a different server or site collection (unless you are developing directly on your production server, which is not recommended). To deploy your workflow, perform the following steps.

To deploy the workflow

  1. Copy the DLL your workflow creates from the build directory (\bin\Debug\ or \bin\Release) to the global assembly cache of the target server.

  2. Create a directory in the FEATURES directory (typically, the path is drive:\Program Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATURES). Drop both the feature.xml and workflow.xml files into the directory.

  3. Install the feature on your farm by using the following command-line statement: stsadm –o installfeature –name SimpleSequentialDocumentReview

  4. Activate the feature on a site collection by using the following command-line statement: stsadm –o activatefeature –name SimpleSequentialDocumentReview –url http://moss.litwareinc.com

Conclusion

Workflow development with Microsoft Visual Studio 2008 is greatly simplified to provide a more traditional development experience: Visually design the workflow structure, add code to handle events associated with workflow activities and the functionality you want, and then press F5 to debug the workflow.

Workflows consist of activities. To develop a workflow, you add activities to the workflow designer, set or configure the properties associated with each activity, and then add any code you want to respond to events associated with activities. Windows Workflow Foundation includes many activities designed to perform specific types of tasks. Microsoft Office SharePoint Server 2007 includes additional activities specific to SharePoint workflows. In Visual Studio, you add an activity to a workflow by dragging it from the Toolbox and dropping it in the desired location on the designer.

Some activities can be configured at design time, but you may often need to set activity properties at run time, implement logic, or perform related tasks when an activity occurs. To do this, you can attach event handlers to activity events, for example, the Invoked event. Just as you would generate an event handler for a control on a user control, you can generate an event handler for the Invoked event just by double-clicking in the Invoked property value while viewing the events associated with the activity in the Properties window.

Finally, debugging workflows by using Visual Studio 2008 is trivial compared to the task in earlier versions of Visual Studio. Simply press F5 in Visual Studio to start debugging the workflow. Visual Studio takes care of compiling the workflow, deploying the workflow to Office SharePoint Server, associating the workflow with your target document library or list, attaching to the W3WP process, and opening an instance of Internet Explorer displaying the correct page (the document library or list that the workflow is associated with). Previously in Visual Studio, you had to perform all of these chores manually.

About the Author

Steve Hansen is an Office system architect at Dakota Technology Group. Steve is a Microsoft MVP for Visual Studio Tools for Office. In his free time, Steve writes Microsoft Visual Basic for Applications and Visual Studio Tools for Office tips for VBATips.com and VSTOTips.com. Steve has created numerous (over 50) videos for Microsoft that are related to Visual Studio Tools for Office development. Find these videos on MSDN at How Do I Videos - Office.

This article was developed in partnership with Dakota Technology Group, Inc. For more information about Microsoft Office products, visit Microsoft Office Online.

Additional Resources