InformIT

Windows Workflow Foundation: March Through the Activities

Date: Nov 4, 2005

Sample Chapter is provided courtesy of Sams.

Return to the article

Activities are the building blocks of a workflow. A number of activities are provided in the Visual Studio 2005 toolbox to create basic workflows. You can also easily create your own activities, which can be added to the toolbox for use in your workflows. This chapter introduces you to all the activities that come with Windows Workflow Foundation.

In this chapter

Activities are the building blocks of a workflow. A number of activities are provided in the Visual Studio 2005 toolbox to create basic workflows. You can also easily create your own activities, which can be added to the toolbox for use in your workflows.

As such, activities are the first point of extensibility for Windows Workflow Foundation. Custom activities can be built that are treated the same as primitive activities that come with Windows Workflow Foundation. Also, custom activities can be built to relate to specific application domains for end-user applications. These custom activities, when targeted at a suitable higher level, could provide a nondeveloper design experience. You can build activities to be used with the workflow application that you build, or you can use activities that come from third-party software.

This chapter introduces you to all the activities that come with Windows Workflow Foundation.

Table of Activities

Table 3.1 provides a reference list of all the activities provided in the toolbox for Windows Workflow Foundation in Visual Studio 2005. This list is the same order as the Visual Studio 2005 toolbox; however, not all of these activities will be present depending on the workflow project template selected.

Table 3.1 Activities Provided in the Toolbox for Windows Workflow Foundation in Visual Studio 2005

Activity Name

Description

Sequence

Container for sequentially executed activities

Parallel

Two or more sequences executed in parallel

While

Repeats activities while condition is true

IfElse

Executes activities if a condition is true

Listen

Waits for one of a set of events

EventDriven

Used in a Listen or a workflow event handler to specify the event and contain the executed activities

Delay

Causes the containing branch of the workflow to wait for a timeout

ConditionedActivity Group

A list of activities executed on a variety of conditions

Replicator

Executes multiple copies of a contained activity

TransactionalContext

Contains activities involved in short- or long-term transactions

ExceptionHandler

Contains exception-handling activities

Throw

Throws an exception from a workflow or scope

Compensate

Used in an exception handler body to reference the required compensation

Code

Executes a specified method in the code-beside file

InvokeWebService

Makes a call out to a web service

InvokeWorkflow

Makes a call out to another workflow

UpdateData

Sends an instance of a predefined class of data to the host

SelectData

Requests an instance of a predefined class of data from the host

WaitForData

Accepts an instance of a predefined class of data from the host

WaitForQuery

Accepts a request for an instance of a predefined class of data from the host

WebServiceReceive

Waits for an external web service call to the workflow

WebServiceResponse

Sends a response to an external web service call from the workflow

Suspend

Stops the workflow instance from running; it can be restarted

Terminate

Shuts down this workflow instance

State

Defines a state in a workflow

StateInitialization

Contains activities that are executed on entering a state

SetState

Initiates a state transition in a state machine


Container for Activities

Some activities can act as a container for other activities. This is in addition to the workflows that contain activities. This list shows the main items that can act as containers of activities in the workflow designer:

A few activities such as sequential workflows (a workflow is a special kind of activity) and TransactionalContexts have complex definitions that are presented as multiple views. These consist of the main sequence, exceptions, events, and compensation. The workflow designer provides access to these views through tabs and the context menu.

Figure 3.1 shows the tabs for the four views. You view each design surface by clicking on the respective tab. A Scope activity has the same selections in the context menu, which you access by right-clicking on it.

Figure 3.1

Figure 3.1 The tabs in the workflow designer from Visual Studio 2005.

Conditions

Several activities (While, IfElse, ConditionedActivityGroup, and Replicator) can have conditions or rules associated with them. Each condition returns either true or false. There are three possible condition types available:

Any of these types of conditions can operate on shared workflow instance state in the workflow as described by public member variables. In each case a true or false result is fed back into the activity execution.

Declarative Condition

The condition property of an activity must be set to the type of condition being used. You select rules by setting the condition property to System.Workflow.Activities.Rules. RuleConditionReference. Once selected, a [+] symbol appears next to the condition property. You can click on this symbol to show the condition details. Click on the condition details to show the declarative condition that is associated with your workflow.

You can choose a declarative condition from the list, and add or edit declarative conditions in the list. Figure 3.2 shows the rules editor that displays when you add a declarative condition.

Figure 3.2

Figure 3.2 The Declarative Condition Editor.

In the Declarative Condition Editor you can add logical operators to the condition (AND, OR, and NOT). You can also add predicates. A predicate is a binary operator and two operands. The binary operators supported are ==, >, <, >=, and <=. Supported operands are constant value, arithmetic function, and scoped member, which refers to a workflow instance variable. You can specify the type for the comparison and you can compare to null or an empty string.

Complex conditions can be created based on workflow instance member variables.

Control Flow Activities

Control flow activities help to define the basic structure of a workflow.

Sequence Activity

The Sequence activity (shown in Figure 3.3) is a basic building block activity that expresses the idea of doing one thing, and then another. It executes contained activities sequentially. A sequential workflow is a special kind of sequence.

Figure 3.3

Figure 3.3 A Sequence activity.

The sequence is also useful because some activity types that will contain other activities can only contain a single activity. You can only put multiple activities in them if you first add a more general container activity such as a sequence.

The Sequence activity has properties of ID, Description, and Commented. If the Commented property is set to true (see Figure 3.4) the activity will not be part of validation or exception. It also appears a shaded green color in the designer. This is very similar to commenting out code.

Figure 3.4

Figure 3.4 A commented Sequence activity.

Parallel Activity

Parallel activities (as shown in Figure 3.5) allow multiple activities to execute concurrently. It could be that there are several external requests to be made and they each take several days to respond. Or there may be a collection of short web services to call, each taking two to three seconds to respond. The Parallel activity allows requests to be initiated in parallel and may reduce the overall time it takes to complete them.

When it is initially dragged from the toolbox, the Parallel activity contains two paths of execution. You can add more by using the context menu for the Parallel activity or using the Add Branch command in the Properties pane.

Figure 3.5

Figure 3.5 A Parallel activity.

IfElse Activity

The IfElse activity executes contained activities if a condition is true.

In Figure 3.6 there are two branches. The first branch is required to have a condition and the red circle and exclamation point indicate that there is no default condition. It must be added to avoid the error.

The last branch in an IfElse is not required to have a condition though if it had one it would be like an If-EndIf structure that has no Else. The IfElse activity evaluates the leftmost branch first. If that condition returns true the activities on that branch are executed; otherwise it evaluates the next branch, and so on.

You can add branches to an IfElse in much the same way that you can add branches to a Parallel.

While Activity

The While activity executes contained activities while the condition is true. A While activity can only contain a single child activity, so this is a place where you might use a Sequence or a Parallel or another multiactivity container.

Figure 3.6

Figure 3.6 An IfElse activity.

The designer representation of the While activity in Figure 3.7 gives a good visual as to what it does. The condition is first evaluated; if it is true the contained activity is executed, and then you loop around and the loop repeats until the condition is false.

Figure 3.7

Figure 3.7 A While activity.

For-Next Loop Implemented with a While Activity

The workflow in Figure 3.8 shows how you can use a While activity as a For-Next loop. The While loops around and executes the code1 activity five times.

Figure 3.8

Figure 3.8 A workflow showing a While activity as a For-Next loop.

The While activity has a declarative condition, shown in Figure 3.9, that returns true if the LoopVariable is less than 5.

Figure 3.9

Figure 3.9 The Declarative Condition Editor showing a loop.

The class for the workflow contains the declaration for the instance variable and the code-beside method for the Code activity. In Listing 3.1, the Code activity writes a message and increments the LoopVariable.

Listing 3.1 Implementation Class of a For Loop

  <RuleConditionsAttribute(GetType(Workflow1))> _
  Partial Public Class Workflow1
    Inherits SequentialWorkflow

    Public LoopVariable As Integer

    Public Sub New()
      MyBase.New()
      InitializeComponent()

      LoopVariable = 0
    End Sub

    Private Sub code1_ExecuteCode(ByVal sender As System.Object, _
                   ByVal e As System.EventArgs)
      Console.WriteLine("Hello Again")
      LoopVariable = LoopVariable + 1
    End Sub
  End Class

ConditionedActivityGroup Activity

The ConditionedActivityGroup activity (shown in Figure 3.10) loops through a collection of activities, executing them until an Until condition is true. Each activity in the collection is executed according to a When condition and an Unless condition. These three types of conditions default so that each activity is executed once only.

Figure 3.10

Figure 3.10 A ConditionedActivityGroup activity.

For more information on the ConditionedActivityGroup activity see Chapter 8, "Advanced Activities and Activity Behaviors."

Replicator Activity

The Replicator activity, shown in Figure 3.11, contains a single activity. At runtime it executes multiple copies of that activity. It is particularly useful for a human-based workflow where a number of approvers are required, the exact number is not known until runtime.

Figure 3.11

Figure 3.11 A Replicator activity.

For more information on the Replicator activity see Chapter 8.

Delay Activity

The Delay activity causes the containing branch of the workflow to wait for a specified amount of time. The workflow may be dehydrated during the delay if it becomes completely idle and rehydrated when the time expires.

Delay has a property called TimeoutDuration that is a TimeSpan with a default value of 00:00:00. You can either specify a value for TimeoutDuration or you can implement the InitializeTimeoutDuration() handler, which is called to set the TimeoutDuration property.

You can use a Delay activity to delay until a specific time if you calculate the TimeSpan between now and then yourself. For example, if you wanted to delay until 2:30 a.m. tomorrow morning you could use the code in Listing 3.2 in your InitializeTimeoutDuration().

Listing 3.2 InitializeTimeout to Wait Until a Set Time

  Public Sub delay1_InitializeTimeoutDuration(ByVal sender As Object, _
                        ByVal e As EventArgs)
    ‘ find time today
    Dim NextStop As DateTime = DateTime.Today
    NextStop = NextStop.AddHours(2).AddMinutes(30)

    ‘ if time past today then wait until tomorrow
    If (NextStop <= DateTime.Now) Then
      NextStop = NextStop.AddDays(1)
    End If

    CType(sender,Delay).TimeoutDuration = NextStop.Subtract(DateTime.Now)
  End Sub

You might use a Delay activity to

Workflow Lifetime Activities

Activities that affect the lifetime of a workflow are known as workflow lifetime activities, described in the following sections.

InvokeWorkflow Activity

The InvokeWorkflow activity (see Figure 3.12) is used to execute another workflow asynchronously. The InvokeWorkflow activity completes immediately (before the launched workflow starts executing) and the next activity in the branch is executed.

Suspend Activity

The Suspend activity (shown in Figure 3.13) temporarily stops the execution of the current workflow. It can pass an error message back to the host, which can be specified through the Error property in the Suspend activity. The Error property can refer to a string literal, a field or property reference, or an activity reference.

Suspended workflow instances can still receive messages that are queued up until the workflow is restarted. The workflow can only be restarted by the host by calling Resume() on the WorkflowInstance class.

Figure 3.12

Figure 3.12 An InvokeWorkflow activity.

Figure 3.13

Figure 3.13 A Suspend activity.

Terminate Activity

A workflow normally completes after all activity branches are finished. If something unexpected occurs in the workflow an exception can be thrown. But an exception can be caught and handled which, depending on the problem, may not be desirable. The Terminate activity (shown in Figure 3.14) guarantees that no other activity will run after this one. As with the suspend activity you can pass an error message back to the host.

Event Waiting Activities

Some activities wait for an event, as the following sections illustrate.

EventDriven Activity

The EventDriven activity is a special kind of sequence where the first activity in the sequence must be an activity that waits for an event. This includes activities such as a WaitForData, WaitForQuery, WebServiceReceive, Delay, or a custom-built event-sink activity in a Local Communications Service project. The EventDriven activity can only be used in two specific places:

Figure 3.14

Figure 3.14 A Terminate activity.

Listen Activity

The Listen activity (shown in Figure 3.16) waits on multiple events at once. The Listen activity contains multiple EventDriven activities to achieve this. Only one event waiting activity (the first to receive an event) ever gets run in each execution of a Listen. When the event is received the subsequent activities in that sequence are executed as in a regular sequence.

Figure 3.15

Figure 3.15 The Workflow Events design surface.

Figure 3.16

Figure 3.16 A Listen activity with contained EventDriven activities.

Typically one of the paths in a Listen contains a Delay. The Delay activity is implemented as an event that occurs after a timeout.

The Listen activity in Figure 3.17 contains two EventDriven paths. The first one waits for a web service call into the workflow. The second one is a Delay. If the Delay timeout occurs first then the web service receive will stop and the workflow will continue with activities following the Delay.

Transaction and Exception Activities

Transactions apply to workflows and to transactional/context activities. If a transactional/ context is used, the workflow can continue after any exception has occurred. If an exception is caught at the workflow level it can be handled but the workflow cannot continue.

TransactionalContext Activity

The TransactionalContext activity provides short- and long-term transaction support, exception-handling support, and event-handling support. It defines the transaction boundary and contains all the activities that are to be part of the transaction. This section focuses on catching transaction exceptions at the workflow level.

The TransactionalContext activity actually refers to a set of behaviors that are described in Chapter 8.

Figure 3.17

Figure 3.17 A Listen activity with a Delay path and a Web Service path.

Throw Activity

An exception may be thrown using the Throw activity (shown in Figure 3.18) from within a workflow or within a transactional/context. An exception may also be thrown by another activity on an error condition. Workflows use the second tab on the lower-left of the design surface as shown in Figure 3.1 for accessing the exceptions views. For the exception view of a Transactional/context use the context menu in a Scope to access the exception view.

Figure 3.18

Figure 3.18 A Throw activity.

When an exception is thrown it will terminate the workflow immediately unless it is caught. To catch an exception in the workflow click on the View Exceptions tab to show the Exceptions view. The Exceptions view is where you can drag and drop exception handlers.

ExceptionHandler Activity

Exception handlers can only be dragged and dropped to the Exceptions view. Figure 3.19 shows the Exceptions view with no exception handlers. The Scope exceptions view behaves in a similar way.

Figure 3.19

Figure 3.19 The Workflow exceptions design surface.

To catch an exception, you must drag and drop an exception handler from the toolbox and have properties configured. You can drag and drop any number of exception handlers to handle different kinds of exceptions in different ways. In this way, an ExceptionHandler activity functions just like a catch block in code. Figure 3.20 shows the exceptions view with one exception handler and a Code activity added to the body of the exception handler.

In Figure 3.20 the code2 activity will be executed if the exception handler catches an exception. The Code activity has access to the specific exception through a variable specified in the Variable property of the exception handler. The Type property specifies what exceptions will be caught by this exception handler. If the Type property is set to System.Exception, all exceptions will be caught by this exception handler.

For a long-running transaction a Compensate activity is added to the exception handler body.

Compensate Activity

The Compensate activity (shown in Figure 3.21) can only be added to the body of an exception handler. It is used to point to compensation logic that is required to roll back any long-running transaction that has failed. Failure of a long-running transaction is identified by an exception being raised. This figure shows a Compensate activity in the body of an exception handler. For more detail see Chapter 8.

Figure 3.20

Figure 3.20 The Workflow exceptions design surface with one exception handler.

Figure 3.21

Figure 3.21 An exception handler that contains a Code and a Compensate.

Data-Centric Activities

The data-centric (or form-centric) activities are a simple mechanism for workflow to host communication and vice versa. This communication centers around a data class that defines the structure of the communicated data.

There are four activities in this group and among them they allow for both proactive and reactive, requests and submits of data, to and from the workflow and host.

In other words, to look at things from the workflow point of view, looking at the host:

And from the host point of view, looking at the workflow:

A data source is created in the workflow. The data source refers to the data class and a class that implements the host interface IDataHandler. Think of this as the interface class. An ID property in the data class is used as part of correlating a data update from the host with a WaitForData or WaitForQuery.

Chapter 5, "Workflow Integration with Data Activitites," has more detail on these four activities:

Web Services Activities

Windows Workflow Foundation has built-in support for calling web services and for publishing a workflow as a web service.

See Chapter 6, "Using Web Services," for a detailed discussion of these activities:

The Code Activity

The code activity stands alone. It permits quick adding of a code handler anywhere in the workflow.

A Code activity (shown in Figure 3.22) enables you to add some C# or Visual Basic .NET code into any part of a workflow just by dragging it in and double-clicking on it. This is a very simple form of a custom activity. The code entered in this way lives in the code-beside file that is compiled with the workflow.

Figure 3.22

Figure 3.22 A Code activity.

State Workflow Activities

A finite state machine is a standard programming pattern in which behavior responds to events differently depending on a recorded state. Action occurs on state transitions that are triggered by events.

These activities are all specific to the State Machine workflow style and they only appear on the toolbox when you are using the State Machine workflow designer.

State Activity

The State activity (shown in Figure 3.23) represents one state that the state machine can be in. When you create a new state machine workflow you always start with one state on the design surface.

Figure 3.23

Figure 3.23 The Workflow1 initial state.

StateInitialization Activity

Each state activity must either contain an EventDriven activity or a StateInitialization activity. The StateInitialization activity can have action activities dragged into it to execute on the change to the state.

SetState Activity

The SetState activity (shown in Figure 3.24) is dragged into the view of a StateTransitionHandler to specify a new state to change to. It can also appear at the end of an EventDriven sequence.

Figure 3.24

Figure 3.24 A SetState activity.

Custom Activities

Most of the provided activities for Windows Workflow Foundation are related to the structure of a workflow, communications with a workflow, or the lifetime of a workflow. The really important activities are ones related to the application domain of the software you are building. These are all created with custom activities.

InvokeMethod Activity in Communications Library

A workflow communications library project type can be built to create activities that either invoke or handle events. Once built, these appear on the toolbox and can be used to communicate between the workflow and an external system.

The InvokeMethod activity calls out from the workflow to an external system.

EventSink in Communications Library Activity

The EventSink activity waits for an event from outside the workflow. These events arrive via the host process. The EventSink activity can be correlated with a related InvokeMethod call.

There is a discussion of InvokeMethod and EventSink in Chapter 9.

Composite Activity in Activity Library

If you build an Activity Library project template in Visual Studio 2005 you can build an activity yourself easily. You can build an activity using the activity designer (see Figure 3.25), which creates a composite activity from a sequence of pre-existing activities.

Figure 3.25

Figure 3.25 The composite activity designer.

Coded Activity in Activity Library

In the same Activity Library project type you can code an activity in C# or Visual Basic .NET. To do this you change the base class property for the activity from System.Workflow.Activities.Sequence to System.Workflow.ComponentModel.Activity.

See Chapter 7 for more details about creating custom activities.

Summary

This chapter provided you with an overview of all the Workflow activities that appear on the toolbox in Visual Studio 2005 when you are editing a workflow.

800 East 96th Street, Indianapolis, Indiana 46240