learnWorkflow: 3.5 introductions

chapter introductions

What follows are the introduction sections from each chapter. The introduction provides a brief overview of what you'll learn from the chapter.

chapter 1: a quick tour of windows workflow foundation

This chapter presents a brief introduction to Windows Workflow Foundation (WF). Instead of diving deeply into any single workflow topic, it provides you with a sampling of topics that are fully presented in other chapters. You’ll learn why workflows are important and why you might want to develop applications using them. You’ll then jump right in and implement your very first functioning workflow. Additional hands on examples are presented that demonstrate other features of Windows Workflow Foundation.

chapter 2: foundation overview

The purpose of this chapter is to provide a grand tour of Windows Workflow Foundation (WF). It is a high-level description of the discrete parts of WF and how they work together. Because of the summary focus of this chapter, it doesn’t contain much actual workflow code. As you dig deeper and deeper into WF in later chapters, you’ll want to refer back to this chapter to see where individual features fit into the big picture.

The chapter starts with a general discussion of the two major types of workflows, sequential and state machine. Following that, the major components that are delivered with WF are reviewed. This is a birds-eye view of what you get when you install WF on your development machine. Included is an overview of the WF class libraries, the workflow runtime engine, workflow runtime services, and the workflow design time tools.

The remainder of the chapter is split between runtime and design time features. First, I discuss the workflow runtime environment and review the major WF components that you’ll use at runtime. One of your responsibilities when using WF is to provide the host application. The requirements of the host application are summarized along with a discussion of the workflow runtime engine. WF provides the ability to change its default behavior by loading alternate implementations of core services. You can also implement and register local services with the workflow runtime. Both of these types of services are discussed in this chapter. The chapter concludes coverage of the runtime components with a discussion of workflow instances.

The design time environment is covered next. Here I show you the tools that you use to develop workflow applications. In this section, I review workflow authoring modes and project templates followed by a discussion of the workflow designers that are included with WF.

chapter 3: activities

The focus of this chapter is the primary building block of all workflows: the activity. This chapter provides a high-level review of the standard activities that are provided with Windows Workflow Foundation (WF). You will become acquainted with the available activities, but you will not learn how to use all of them in detail. This is the one chapter that provides an overview of all of the available activities. Many of the individual activities are difficult to understand unless they are discussed as part of a larger subject area. For this reason, the subsequent chapters in this book each focus on a specific subject area and provide additional detail on the activities that are relevant to that subject.

One area that is covered in detail in this chapter is how to add logic to your workflow. There are two primary ways to accomplish this, using the CodeActivity, and developing your own custom activities. Both mechanisms are explored and compared using a common workflow example. This chapter also provides additional information on enhancing the design time experience when using custom activities.

chapter 4: hosting the workflow runtime

The focus of this chapter is hosting the workflow runtime within your applications. A simple hosting example is used to illustrate the basic requirements for workflow hosting. A set of workflow manager classes are then developed that address some of the problems and limitations of the first example.

The workflow runtime exposes a number of events that can be handled by your host application. These events allow you to monitor the status changes of running workflows. The examples in this chapter demonstrate how you can handle and use these events within your applications.

This chapter also shows you how to add core workflow services to the runtime in code and via the application configuration file. Core workflow services allow you to customize the behavior of the workflow runtime engine by loading an alternate implementation of a service. Examples in this chapter load the persistence service and an alternate implementation of the scheduler service.

When a workflow is created, an instance of the WorkflowInstance class is returned. This class exposes several methods that permit you to take direct actions on a workflow instance. Several of these methods are demonstrated in this chapter.

Finally, workflows normally execute asynchronously within the workflow runtime engine. However, they can also execute synchronously if you load an alternate scheduler service. The use of this alternate service for synchronous workflow execution is demonstrated in this chapter.

chapter 5: flow control

One of the great advantages to workflows is that they enable you to declaratively control the flow of execution. No longer are you required to tightly couple the business logic (the what and how) with the flow control (the when). You can develop discrete, independent activities containing your reusable business logic and then knit them together using the flow control activities.

The purpose of this chapter is to present the flow control activities that are included with Windows Workflow Foundation (WF). Many of these activities permit you to define conditions that determine when an activity executes, so the chapter begins with a brief discussion of the two types of conditions: code and rule.

The IfElseActivity allows you to declare simple branching decisions within a workflow. The use of this activity is demonstrated with two example workflows. The first example is implemented with code conditions and the second uses rule conditions.

The WhileActivity provides the ability to repeatedly execute an activity while a condition is true. The ParallelActivity enables the definition of multiple branches of child activities with turnbased execution of each branch. The ReplicatorActivity is similar to the C# foreach statement, creating an instance of a child activity for each element in a collection of input data. This activity is useful when you need a data-driven workflow that can easily adapt and respond to the incoming data. This chapter includes a full discussion of each of these activities along with example workflows that demonstrate their use.

Also included is coverage of the ConditionedActivityGroup, a complex hybrid activity that exhibits some of the behavior of the WhileActivity and the ParallelActivity. The chapter concludes with a discussion of the InvokeWorkflowActivity, TerminateActivity, and SuspendActivity.

chapter 6: local services

Windows Workflow Foundation (WF) provides the ability to optionally register services with the workflow runtime engine. This ability provides an extensible way to modify the behavior of the workflow runtime. WF defines a set of core workflow services that handle thread scheduling, workflow persistence, transactions, and workflow tracking. The designers of WF could have embedded the implementation of these services in the runtime engine itself, but they wisely chose to externalize them, placing their implementations in pluggable services. This places you in control. You decide which services to use (some are optional) and which implementation to use for each service.

WF also supports another kind of service known as a local service (sometimes called a data exchange service). This is a service that you design and implement yourself. A local service can serve just about any purpose, but one general use is to facilitate communications between workflow instances and the host application. In contrast with this, core workflow services each have a purpose (e.g., persistence, tracking) that has been defined by Microsoft. You can develop alternate implementations for each core service, but that doesn’t change their defined purpose.

The goal of this chapter is to discuss the implementation and use of local services. An example local service is first implemented and then added to the workflow runtime engine, making it available to workflow instances. A local service can be created via code or from entries in an application configuration file. Both mechanisms are demonstrated in this chapter.

Once a local service is loaded, it can be referenced and used from a workflow instance. Three different ways to use a local service are demonstrated. First, the example local service is used directly from code in the workflow class. Then a custom activity is developed that uses the same local service. Finally, the standard CallExternalMethodActivity is demonstrated. This activity allows you to declaratively invoke a method on a local service without any code.

chapter 7: event-driven activities

Event-driven activities suspend execution of a workflow until an event is received. The event is commonly raised externally by a local service, but it can also be raised internally from within a workflow. These types of activities are vital to state machine workflows, since they are typically used to trigger state transitions. But they are also a valuable tool for sequential workflows.

The previous chapter began the discussion of local services. It covered the steps needed to implement a local service and then call a method on the service from a workflow. This chapter completes the local services story. It shows you how to implement and raise events in a local service and then handle them within a workflow. Demonstrated in this chapter are the typical patterns used to call an external method and then wait for a response from the host application in the form of one or more events.

The chapter begins with a general discussion of event-driven activities, followed by an example that uses HandleExternalEventActivity to process local service events. This example implements a local service that provides bidirectional communication between a workflow and the host application.

Windows Workflow Foundation (WF) provides an alternative to using CallExternalMethodActivity and HandleExternalEventActivity to communicate with a local service. Using a command-line utility (wca.exe), you can generate strongly typed custom activities that derive from these standard activities. The second example in this chapter demonstrates how to use this utility to generate the custom activities and then use them in a workflow.

The normal correlation logic routes local service events back to the correct workflow based on the workflow instance ID. However, in some situations, this type of correlation isn’t sufficient. You may need a workflow that waits for multiple instances of the same event. WF provides a set of correlation attributes that enable you to control which activity within a workflow receives the event. These correlation attributes are demonstrated in the third example of the chapter.

Following the correlation example, the chapter continues with a discussion and example of EventHandlingScopeActivity and EventHandlersActivity. Unlike the more common form of event handling, these activities enable you to concurrently handle multiple events while executing a mainline set of activities.

The concluding section of the chapter discusses the development of custom event-driven activities and the use of workflow queues for communication. Queuing is the underlying technology used by WF to pass event data to workflow instances. The final example in the chapter revisits the first example, this time implementing a custom event-driven activity that uses a workflow queue to receive data.

chapter 8: workflow persistence

An important capability of workflows is that they can be persisted (saved and reloaded at a later time). Workflow persistence is especially important when developing applications that coordinate human interactions, since those interactions could take a long period of time. But persistence is also applicable to other types of applications. Without persistence, the lifetime of your workflows is limited. When the host application is shut down, any workflow instances simply cease to exist.

Workflow persistence is implemented as one of the optional core workflow services. You need to load a persistence service only if your application requires it.

After taking a brief look at reasons to use persistence, this chapter examines how persistence works in the Windows Workflow Foundation (WF) world. WF includes a standard persistence service that works with SQL Server. This chapter includes an example that demonstrates how to use this persistence service.

The WF persistence logic was implemented as external services in order to permit you to provide your own persistence implementation. The second half of this chapter demonstrates how to implement your own custom persistence service and use it in an application.

chapter 9: state machine workflows

The focus of this chapter is state machine workflows. State machine workflows are different from sequential workflows in a number of ways. Most importantly, they don’t define a hardwired sequence of steps within the workflow. Instead, they define a set of application states with possible transitions between states. Each state can handle multiple external events that trigger execution of child activities including a possible transition to another state.

Because their flow of control is not hardwired into the design of the workflow, they are excellent in situations that require human interaction.

This chapter begins with a brief overview of state machine workflows. This overview includes a discussion of their benefits, as well as a summary of the WF classes that you use when developing state machine workflows.

Following the overview, you will implement an application that uses a state machine workflow to model the basic operations of a car. The example provides step-by-step instructions on how to design and implement the workflow along with a local service that supports the necessary external events. The Windows Forms application enables you to interact with the workflow, raising events that cause the workflow to transition to another state.

Three additional examples in this chapter build upon this first example by making slight improvements to the design. One of these additional examples demonstrates how to eliminate duplicate activities using recursive composition of states. The final two examples show you how to interrogate the workflow runtime to retrieve additional information about a running state machine workflow.

chapter 10: transactions and compensation

Integrity and consistency are important qualities to have when performing work in any application. You generally don’t want to perform work in an inconsistent manner, or in a way that might leave the integrity of the data in doubt. These are important qualities for workflow applications as well as traditional applications.

WF supports several mechanisms that are designed to ensure the integrity and consistency of work that you perform. One mechanism supported by WF is transactions. Transactions allow you to create logical groups of work that use a resource manager such as a relational database. When work is enlisted in a transaction, it is committed or rolled back together. Either all of the work succeeds, or all of it fails. It is designed to always leave the underlying resource (such as a database) in a consistent state.

WF provides support for transactions with the TransactionScopeActivity. After a general discussion of transactions, the first example in this chapter demonstrates the use of this activity to enlist multiple database updates in a single batch of work.

WF also supports compensation. Compensation is a standardized way to undo work that is already completed. You can use compensation in those situations where a long-running transaction is not feasible. The second example in this chapter demonstrates the use of the CompensatableTransactionScopeActivity and the CompensatableSequenceActivity.

WF also provides you with the flexibility to commit other kinds of work under the control of a transaction. By adding work items to a batch of work, you can coordinate the actual committing of the work with an active transaction. The third example in this chapter demonstrates how to use the IPendingWork interface to accomplish this.

chapter 11: workflow rules

WF provides a flexible rules evaluation engine that you can use when developing applications. Rules are an alternate way to implement business requirements and they complement the other mechanisms that are provided with WF. A rule is simply a declarative statement about your data. Within a rule, you declare a condition that you wish to evaluate at runtime. If the condition evaluates to true, one or more actions that you define are executed. A rule also permits you to define actions to execute when the condition evaluates to false. The rules support in WF includes a rules editor that allows you to declare individual rules and group them together into rule sets.

After a summary of the rules support in WF, a series of examples are presented that demonstrate the features of workflow rules.

The first example walks you through the process of declaring a set of rules and then executing them within a workflow using the PolicyActivity. Rules tracing is also enabled and the trace log is reviewed. The trace log provides insights into just how the rules engine evaluates each of the rules.

The chapter then builds on this first example workflow with a series of shorter examples that explore other features of rules. For instance, one example shows you how to adjust the execution sequence for individual rules. Following that example, the rules are modified to reference workflow methods instead of properties. A set of rule attributes are applied to the methods to provide dependency information to the rules engine.

You can also execute rules in code instead of using the PolicyActivity. Two short examples demonstrate ways to execute rules entirely in code. The first example demonstrates code to deserialize and execute a rule set that was previously saved while the second example creates a rule entirely in code.

chapter 12: exception and error handling

The focus of this chapter is exception and error handling. WF provides a way to declaratively handle exceptions within the workflow model. While this doesn’t completely eliminate the need to handle exceptions within your code, it does allow you to declare some cleanup logic within the workflow model, enabling easier changes to the logic as it becomes necessary.

This chapter begins with an overview of workflow exception handling. It then presents a series of short examples that demonstrate how to use the FaultHandlerActivity to declaratively define exception logic within a workflow.

Exception handling is used to clean up work for incomplete activities while compensation (covered in Chapter 10) is the undoing of work that has completed. The two mechanisms are designed to address a different set of problems. This chapter includes an example that shows you how to use both mechanisms within the same workflow.

Finally, WF also provides a way to declare activities to execute when a composite activity is canceled. The use of the CancellationHandlerActivity is demonstrated in the final section of the chapter.

chapter 13: advanced custom activities

This chapter provides additional information on several topics that will assist you with the development of custom activities. The use of simple custom activities has already been demonstrated earlier in this book. Those activities derived from the base Activity class, which doesn’t support child activities.

This chapter begins with an exploration of custom composite activities. Unlike simple activities, composite activities support the execution of child activities. Custom composite activities that are fit-for-purpose are demonstrated first. These are composite activities that are designed to solve a narrowly focused business problem. They include only the set of child activities that are needed to solve their particular business problem and don’t permit additional activities to be added after they are built.

In contrast with fit-for-purpose activities, general-purpose composite activities are designed as containers for other activities. Their sole purpose in life is to manage the execution of their child activities according to their predefined execution pattern. After a brief discussion of general-purpose compositeactivities, the chapter continues with an example activity that reproduces the behavior of the standard SequenceActivity. The example code is then enhanced to use a different execution pattern that processes child activities according to their relative priority.

Each workflow instance is limited to a single thread of execution. The WF model doesn’t support the creation of additional threads of execution within a workflow. This causes potential problems with long-running tasks since an activity could monopolize the thread and prevent the processing of other scheduled events for the workflow. The chapter concludes with a discussion and example that demonstrates how to implement long-running tasks in a way that conforms to the WF execution model.

chapter 14: dynamic workflow updates

The focus of this chapter is dynamic workflow updates. WF provides the ability to make dynamic changes to the structure of a workflow instance. Structural changes might include adding or removing activities based on updated business requirements. When updates are applied to a workflow instance, they only affect that one instance. All other instances of the same workflow, current and future, use the original workflow definition.

This chapter begins with an overview of the dynamic update process. Following the overview, a series of examples are presented that demonstrate how to apply a set of changes to a workflow instance. The first two examples demonstrate external changes to a workflow instance, where the host application is applying the updates. The next example shows you how to dynamically update a workflow instance from within the workflow.

The rule definitions for a workflow are a likely candidate for dynamic updates. The last two examples in the chapter show you how to update a single rule condition from the host application, and how to completely replace the rule definitions for a workflow.

chapter 15: workflow tracking

The focus of this chapter is workflow tracking. Tracking is a built-in mechanism that automatically instruments your workflows. By simply adding a tracking service to the workflow runtime, you are able to track and record status and event data related to each workflow and each activity within a workflow.

The chapter begins with a general discussion and overview of the tracking mechanism provided by WF. The first example in this chapter introduces the SqlTrackingService, which is a ready-to-use service that records tracking data to a SQL Server database. A follow-up example demonstrates how to enhance the default tracking to create user tracking points within your workflow or activity code. Additional examples show you how to view tracking data for each rule that is evaluated and how to extract values from individual fields in a workflow. The use of custom tracking profiles is also demonstrated.

The database used by the SqlTrackingService does require some routine maintenance. This is discussed in a section that follows the SQL tracking examples.

The chapter concludes with an example implementation of a custom tracking service. This service writes the tracking data directly to the Console instead of persisting it.

chapter 16: web services and ASP.NET

The focus of this chapter is web services and the use of workflows from ASP.NET applications. WF provides support for web services in a number of ways. You can develop a workflow and expose it to clients as a web service. You can also invoke a web service declaratively from a workflow. WF also permits you to host the workflow runtime and invoke workflows from an ASP.NET client application.

The first example in this chapter demonstrates how to publish a workflow as a web service. A follow-up example enhances the example workflow to send web service fault information back to the calling client. In these first examples, the workflow instance completes when the response is sent back to the calling client. WF also supports stateful workflows where a web service client can make repeated calls to the same workflow instance. This is presented in another example.

Other examples included in this chapter show you how to invoke a web service from within a workflow and how to invoke a workflow from an ASP.NET Web Forms application.

chapter 17: workflow services and wcf integration

As you saw in the previous chapter, WF provides standard activities that allow you to expose a workflow as a web service. A workflow can also act as the consumer of web services. With the .NET Framework 3.5, Microsoft has provided additional components to integrate workflows with Windows Communication Foundation (WCF). The result of this integration is called workflow services. Using a new set of standard activities, a new service host for the workflow runtime, and a new set of WCF bindings, you can now expose a workflow as a WCF service or directly consume WCF services from within a workflow.

Note: All of the workflow features described in this chapter require .NET 3.5. If you are targeting a previous release of .NET, these features are unavailable to you.

This chapter begins with a brief overview of WCF followed by an explanation of the WCF support that has been added to WF. In the first example of the chapter, you will create a simple stateless workflow service and test it using the WCF development host and client provided with Visual Studio. You will then host this workflow in IIS and access it from a client application. In addition to hosting workflow services in IIS, you can also develop your own hosting application. To demonstrate this, a self-hosting application is developed for this same workflow.

When developing workflow services, you usually start with a service contract (an interface) and implement it with a workflow. Also demonstrated is an authoring mode called workflow-first where the service contract is defined as a by-product of the workflow implementation.

One of the powerful features of workflow services is the ability to design and implement stateful services. These workflow services maintain their state and permit a client to interact with the same instance for multiple operations.

The use of the SendActivity is also demonstrated. This activity enables you to invoke a WCF service operation declaratively from within a workflow.

The chapter concludes with a large example that demonstrates a conversation between multiple workflow instances. This final example also covers fault handling and the retrieval and use of the workflow runtime from the workflow service host.

chapter 18: workflow serialization and markup

The focus of this chapter is the use of workflow markup and serialization. WF provides several authoring modes that you can use when defining the workflow model. This chapter discusses those authoring modes, spending most of the time demonstrating the use of workflow markup. Workflow markup is a serialized representation of the workflow model that is saved as a .xoml file.

The chapter begins with an overview discussion of each authoring mode supported by WF. Following the overview, examples are presented that implement the same workflow using each authoring mode. The chapter includes examples using the code-only, code-separation, and nocode authoring modes. Several examples also demonstrate how rules are used with each authoring mode.

In addition to authoring modes and workflow markup, this chapter also discusses serialization and deserialization of the workflow model. The serialization techniques demonstrated in this chapter are useful if your application hosts the workflow designers or otherwise requires the ability to modify the workflow model. Several examples also show you how to compile workflow markup to a new assembly using the WorkflowCompiler class and the wfc.exe command-line workflow compiler.

chapter 19: hosting the workflow designers

The focus of this chapter is hosting the workflow designers in your own application. You might need to do this if you want to provide someone other than a Visual Studio developer with the ability to modify workflow definitions. Hosting a customized version of the workflow designers goes hand in hand with no-code workflows. The main advantage of using no-code workflows is that they are distributed in a form that is easy to modify (.xoml markup files). A customized workflow designer provides a way to modify those markup files.

This chapter begins with an overview of the classes and interfaces that are used to build a designer application. Following this brief overview, the chapter presents the code for a working workflow designer application. This is not a general-purpose designer that takes the place of Visual Studio. Instead, it targets the narrow set of functionality needed to maintain no-code workflows. After reviewing the code for this working example, you should be able to apply the basic ideas and concepts presented here to your own designer application that is customized for your needs.