Hour 2 A Spin Around Windows Workflow Foundation

What You’ll Learn in This Hour:

Image   Creating a workflow with basic activities and rules

Image   Adding parameters to a workflow

Image   Creating a XAML + code workflow

Image   Creating XAML-only workflows

In this hour, you will create a sequential workflow using selected Base Activity Library (BAL) activities. You add both code conditions and declarative rules and run and debug the workflow. Then you re-create the workflow as a code-separated workflow, edit the XAML, and run it from the console host as an XML text reader.

As this hour’s name implies, its intent is to give you a basic understanding of many of WF’s features.

Creating a Basic Workflow

The basic concept of developing a workflow is covered in this section. This will be expanded on in later hours when, among other items, you learn more about advanced host-workflow data exchange options and workflow events. The goal here is to get you up to speed with the WF basics.

Creating a Workflow Project

There are six workflow project types in Visual Studio. The most basic, the Empty Workflow Project, references the workflow DLLs, adds some namespace declarations, and enables the workflow debugger. All other workflow projects build on this project. There are two sequential workflow projects. The Sequential Workflow Console Host project creates a console host for the workflow. Generally, you will use this project type when creating a simple project or for testing purposes. The Sequential Workflow Library creates a workflow but no host. Separating the workflows from the host is usually a good idea because it makes it easier to reuse workflows across multiple hosts. There are two state machine workflow projects as well that follow the sequential workflow project pattern. Finally, there is a workflow activity project type that is used to create custom activities.

Image

If you have problems debugging workflows, it may be because your project was created from a non-workflow project that manually referenced the WF assemblies.

Image

If you’re using Visual Studio 2005, expand the Project Types and select Workflow instead of selecting C# first in step 2.

Use the following steps to create a Sequential Workflow Console Application project now:

1.   Start Visual Studio 2008. Select File, New, Project.

2.   Expand the Visual C# project templates and select Workflow.

3.   Select the Sequential Workflow Console Application project template.

4.   Enter FirstWorkflowProject as the Name.

5.   Enter or browse to C:SamsWf24hrsHoursHour02ASpinAroundWF for the Location.

      Your screen should now match Figure 2.1.

FIGURE 2.1 The New Project dialog.

The New Project dialog.

6.   Select OK.

You have now created a Sequential Workflow Console Project.

Image

Remember to substitute your path if you are not using C:SamsWf24hrsHours as the root for your exercises in this book.

Building and Running a Workflow

In the next subsection you add activities to the workflow. In the immediately following section, you will learn to pause the host application so that you can see results printed to the console by the workflow.

Adding Activities to the Workflow

The workflow is a class, or two partial classes. One class holds the activities. The other holds the code-beside logic for these controls. By default, one file with a .cs extension (Workflow1.cs) contains the code-beside logic and another, named .designer.cs, holds the activities on the workflow. This structure is the same as for a form in a Windows Forms application. The activities may also be stored in XML, as will be discussed later in the “Examining the Project Files” section.

1.   Right-click Workflow1.cs in the Solution Explorer and select View Code to open the workflow in code view. You will see some namespace declarations and a Workflow1 class with a constructor. The constructor is the method with the same name as the class. Again, this is very similar to what you would see in the code-behind section of a form in a Windows Forms application.

2.   Double-click Workflow1.cs in the Solution Explorer to open the workflow in design mode (see Figure 2.2). This is the designer.cs file being opened by the workflow designer. I will refer to this as design mode throughout the book. The combination of the two—the .cs and the designer.cs form—represent the entire workflow class.

FIGURE 2.2 Workflow designer and toolbox with BAL activities.

Workflow designer and toolbox with BAL activities.

3.   Select View, Toolbox and click the + to the left of the Windows Workflow v3.0 section to bring up the BAL activities (they are also visible in the left portion of Figure 2.2) that you will drag and drop onto the workflow and then set their properties. If the tack is not pointing down, click it to pin them. This way they will remain in place when you move your cursor away from the Toolbox.

4.   The properties of the currently selected activity (or workflow if none is selected) are displayed in the Properties window, and the project files are displayed in the Solution Explorer. The Solution Explorer can be seen in the upper-right section and the Properties Window in the lower-right section of Figure 2.2.

5.   Drag and drop a Code activity onto the workflow.

6.   Click the Code activity and view its properties in the Property window. Click View, Properties Window, if it is not showing. The Name, Description, and Enabled properties are common to all activities. Enabled is particularly useful because it allows you to retain activities that do not execute on a workflow, which frequently comes in handy. It is equivalent to commenting out code. The ExecuteCode property, on the other hand, is specific to the Code activity. It points to a handler that executes when the Code activity is executed. Figure 2.3 shows the Code activity properties.

FIGURE 2.3 Code activity property window.

Code activity property window.

7.   Double-click the Code activity to create an event hander, and enter the code in the next code snippet:

               Console.WriteLine("The time is {0}",
                    DateTime.Now.ToLongTimeString( ));

8.   Open the workflow in design mode and drag and drop a Delay activity below the Code activity onto the workflow and set its TimeoutDuration property to 00:00:10.

9.   Add another Code activity below the Delay activity, double-click it to get to its handler, and add the same code to its handler that you added to the preceding code activity’s handler.

Your workflow should now look like Figure 2.4. (If there are red exclamation marks, click them to see the errors, and then fix them.)

FIGURE 2.4 First workflow.

First workflow.

You have seen the two views of the workflow. The workflow designer is where you graphically create and view workflows. The code-beside is where you write code to support the activities on the workflow and add variables among other tasks. The workflow designer is analogous to the graphical view of a Windows Form, and the code-beside is analogous to the code-behind of a Windows Form.

Pausing the Host

Add steps to pause the host so that you can see the text printed to the console by the workflow:

1.   Double-click Program.cs in the Solutions Explorer and insert the lines of code shown in the next code snippet below the line that has waitHandle.WaitOne( ) on it so that the content written to the console will not disappear before you can see it:

     // Pause the display
     Console.WriteLine("Press enter to continue.");
     Console.Read( );

Image

Program.cs is the console host. We just added a couple of lines to force the host to pause and allow us to see the text printed to the console when the workflow completes. We cover hosting in more detail in Hours 3 and 17. In this hour, we are relying on the default host outside of these minor changes and a couple of parameters we’ll add shortly.

Building and Debugging the Workflow

Building and debugging a workflow solution is the same as any .NET solution with the one exception that you can insert breakpoints on workflow activities. When debugging, you can use the standard F5, F10, and F11 (start, step over, step into) keys. You can step from workflow activities into workflow code and back out to workflow activities. This is part of the developer-friendly design experience provided by WF.

You will run the workflow three times in this exercise. The first time you will run it with no debugging. The second time you will insert a breakpoint on the first Code activity and step into the code. The third time you will set the breakpoint in the code.

Let’s go through the steps to build and run the workflow now:

1.   Press F5 to build and run the solution (remember to wait 10 seconds for the Delay activity to complete before the second line prints).

2.   You should see the results shown in Figure 2.5.

FIGURE 2.5 First workflow results.

First workflow results.

3.   Double-click Workflow1 in the Solution Explorer to open the workflow in design mode.

4.   Right-click the first Code activity and select Breakpoint, Insert Breakpoint from the drop-down menu.

5.   Press F5 again and notice that the workflow pauses at the breakpoint (see Figure 2.6).

FIGURE 2.6 Workflow stopped on breakpoint.

Workflow stopped on breakpoint.

6.   Press F11 to step in to the Code activity’s handler code.

7.   Notice that you are placed in the source code that you entered. You may step though it and the workflow activities using the standard F10/F11/F5 .NET debugging keys.

8.   When you’re finished stepping through, select the first Code activity and remove its breakpoint by right-clicking it and selecting Breakpoint, Delete Breakpoint.

9.   Double-click the second Code activity and set a standard .NET breakpoint on the first line of its handler’s source code by left-clicking on the margin or pressing F9.

10.   Run the workflow with F5 again and notice that it stops at the breakpoint.

11.   Step through the workflow as you want.

12.   When you’re finished, remove the breakpoints you set on the second Code activity and in the code-beside file.

Enhancing the Workflow

In this section, we will add an IfElse activity to the workflow. The IfElse activity can be thought of as a switch statement with a break inserted in each branch to ensure that it exits after the first true result is returned. Ensuring the correct IfElseBranch executes requires that we delve into rules.

Adding and Removing Activities from the Workflow

1.   Open workflow1 in design mode and drag and drop an IfElse activity anywhere on the workflow.

2.   Drop the first Code activity on the workflow into the left branch of the IfElse activity and the second Code activity on the workflow into the right branch.

3.   Delete the Delay activity from the workflow.

Click the left branch of the IfElse activity. It is named ifElseBranchActivity1. Each branch of an IfElse activity contains an IfElseBranch activity, which are themselves activities. The activities inserted in IfElse activities are identical (with slight differences not now relevant) to Sequence activities. Sequence activities, like the sequential workflow you are now creating, act as containers for other activities. If you like, add a Sequence activity to the workflow and add other activities to it. Now delete the Sequence activity and other activities you added. The significance of the IfElse being a container for IfElseBranch activities that are, in turn, containers for other activities will become evident as we build workflows throughout this book.

Adding a Rule Condition

Let’s go though the steps to create a Code Condition.

1.   Click the first red exclamation mark in the IfElse activity, then click Property ‘Condition’ Is Not Set. You will now be into the Condition property, ready to input a rule to determine whether this IfElseBranch should execute.

2.   In the Properties panel, click the drop-down in the Condition property and select Code Condition.

3.   Click the + at the left of the Condition property, enter CodeBasedCondition into the Condition property, and press Enter.

      You are placed in the CodeBasedCondition handler.

4.   Hard-code the Code Condition to return true by entering the following in the handler. (This is how WF returns a Boolean in a condition, and it represents the beginning of many uses of eventargs in WF):

e.Result = true;

Configuring the Code Activities

Complete the following steps to configure the Code activities.

1.   Switch back to the workflow designer by double-clicking Workflow1.cs in the Solution Explorer.

2.   Double-click the Code activity in the left branch and insert the following code (the cast is to get the activity name):

       // Case the sender object to a codeactivity
       CodeActivity ca = sender as CodeActivity;

      // Print the code activity name
      Console.WriteLine("{0} executed in the left branch", ca.Name);

3.   Now it is time to update the right branch of the IfElse activity (switch back to the workflow designer again).

4.   We will leave the condition blank because we want the right branch to act as an else and to always execute if the other branches (branch in this case) do not.

5.   Double-click the Code activity in the right branch and replace the current code with:

       // Case the sender object to a codeactivity
       CodeActivity ca = sender as CodeActivity;

      // Print the code activity name
      Console.WriteLine("{0} executed in the right-hand branch", ca.Name);

6.   Your workflow should now look like Figure 2.7. See Listing 2.1 directly following for a sample of what your code-beside should look like.

FIGURE 2.7 Enhanced workflow.

Enhanced workflow.

LISTING 2.1 Enhanced Workflow Code Listing


namespace FirstWorkflowProject
{
   public sealed partial class Workflow1: SequentialWorkflowActivity
   {
         public Workflow1( )
         {
              InitializeComponent( );
         }

       private void codeActivity1_ExecuteCode(object sender, EventArgs e)
       {
           // Case the sender object to a codeactivity
           CodeActivity ca = sender as CodeActivity;

           // Print the code activity name
           Console.WriteLine("{0} executed in the left branch"
                             , ca.Name);
       }

       private void codeActivity2_ExecuteCode(object sender, EventArgs e)
       {
           // Case the sender object to a codeactivity
           CodeActivity ca = sender as CodeActivity;

           // Print the code activity name
           Console.WriteLine("{0} executed in the right branch"
                              , ca.Name);
       }

       private void CodeCondition(object sender, ConditionalEventArgs e)
       {
           e.Result = true;
       }
   }

}


7.   Press F5 to run the workflow. The Code activity in the left branch, that is hard-coded to true, should execute and produce the results shown in Figure 2.8:

FIGURE 2.8 First workflow results.

First workflow results.

Go ahead and play around with the Code Condition if you want. You might set the true to false in the condition handler to see if the right branch executes, for instance. This represents our first entry into a workflow that features controls flow logic.

Improving Workflow Transparency

One reason for using WF is to make programs self-evident. Our current implementation, unfortunately, leaves much room for concern in this quest. All we know is that there is a decision that leads the workflow to take different paths. Let’s label our activities to improve workflow comprehensibility. As with all naming schemes, many approaches exist that may, for example, prefix the descriptive names with the type of activity and so on. The purpose of this exercise is solely to show off transparency, not to define an enterprise-level naming convention.

In the next steps, you will change the labels on the workflow activities to improve transparency.

1.   Select the IfElse activity and change its name to CreditEvaluation.

2.   Select the left branch and change its name to CreditPassed, and then change the right branch to CreditFailed.

3.   Rename the Code activity in the left branch ApproveOrder and the one in the right branch RejectOrder.

4.   Look at the workflow to see the improvement. It now serves as a functioning flowchart.

You can now look at the workflow (as shown in Figure 2.9) and see that the purpose of the IfElse activity is to evaluate credit. You can also see which respective paths represent passing and failing credit. The process is now conveyed by looking at the workflow—as it would be if looking at a flowchart.

FIGURE 2.9 Workflow with descriptive names.

Workflow with descriptive names.

Passing Parameters to the Workflow

WF can receive a dictionary object as a parameter from the host when a workflow starts, and the host can access the workflow’s public properties when the workflow completes; it’s very reminiscent of standard method communication patterns. This is done by adding the dictionary object as an additional parameter to the CreateWorkflow method. We are going to use this method of communication in this section. However, this method of communication is usually not the preferred way to conduct host-workflow communication. Workflows are frequently long-running and require mid-process communication to, for example, escalate an approval request if not received on time.

Passing parameters as a dictionary object may be appropriate for workflows that do not require mid-process communication (although persistence described in Hour 3, “Learning Basic Hosting,” may be a problem) and to augment other communication methods. Maybe setup data exists that must be sent to the workflow and it is most convenient to send it to the workflow at startup. Nothing precludes doing this while also using other methods for mid-process communication. Other methods of communication are covered throughout this book beginning in Hour 4, “Learning Host-Workflow Data Exchange.”

Image

.NET 3.5-specific methods of communication that use Windows Communication Foundation are covered in Hour 19, “Learning WF-WCF Integration.”

In the steps that follow, we will now change our Code Condition to compare the value passed in from the host to a constant that will be set on the workflow. This way we can run the workflow once with an amount less than and once with an amount larger than the constant and let the Code Condition determine approval or rejection.

We need to modify the host where we will add a dictionary object and add it to the call to run the workflow instance. We need to modify the code-beside by adding a public property with the same name as the dictionary parameter to enable the exchange.

1.   Open Program.cs and add a parameter above the line that instantiates the workflowInstance (starts with WorkflowInstance instance) with the following code:

     // Add the parameters via a dictionary object
     Dictionary<string, object> parameters = new Dictionary<string,
  object>( );
     parameters.Add("Amount", 900);

2.   Add the parameters to the call to the WorkflowInstance.CreateWorkflow method by replacing the current line that instantiates the workflow instance with the following code:

    WorkflowInstance instance = workflowRuntime.CreateWorkflow
 (typeof(FirstWorkflowProject.Workflow1),parameters);

3.   Open Workflow1 in code view and add a property named Amount below the constructor to receive the information passed to the workflow as shown:

     private int amount;

     public int Amount
     {
         get { return amount; }
         set { amount = value; }
     }

4.   Add a constant below the property you just added to compare against the incoming value and to determine approval status:

     // The approval threshold amount.
     const int maxAmount = 1000;

5.   Replace the current content (e.Result = true;) of the CodeBasedCondition handler with the code shown so that it properly evaluates the amount received from the host to the constant value in the workflow:

     if (Amount < maxAmount)
         e.Result = true;
     else
         e.Result = false;

6.   Open the workflow in design mode, double-click the Code activity in the left branch, and replace the contents in its handler with the following code to reflect its approval:

       // Case the sender object to a codeactivity
        CodeActivity ca = sender as CodeActivity;

      // Print the code activity name
      Console.WriteLine("Approval: {0} executed in the left-hand branch",
         ca.Name);

7.   Open the workflow in design mode, double-click the Code activity in the right branch, and replace the contents in its handler with the following code to reflect its rejection:

      // Case the sender object to a codeactivity
       CodeActivity ca = sender as CodeActivity;

     // Print the code activity name

     Console.WriteLine("Rejection: {0} executed in the right-hand branch",
        ca.Name);

8.   Press F5 to run the workflow.

      The workflow should approve the request because the value of 900 passed in from the host is less than the 1000 constant specified in the workflow, as shown in Figure 2.10.

FIGURE 2.10 Workflow run with approval returned.

Workflow run with approval returned.

9.   Change the Amount parameter in Program.cs to 2000 and run the workflow again, which will result in rejection.

Image

You will learn to retrieve information from the workflow when covering the WorkflowCompleted event in Hour 3, “Learning Basic Hosting.”

Using Declarative Rules

So far you have created Code Conditions to govern workflow control flow. You can also use Declarative Rule Conditions to do the same. Declarative Rules Conditions, or Declarative Rules for short, are stored as XML in .rules files. When creating Code Conditions, you write code inside of a handler. When creating Declarative Rules, you use the Rules Dialog editor (unless you write the XML yourself).

The fact that Declarative Rules are stored in XML is important because rules can be changed at runtime without requiring compilation, can be accessed by tools, and even stored in a database. See Hour 12, “Working with the WF RuleSet,” for more details on rules.

Adding New Activities

Let’s perform the next steps to add a third branch to the IfElse activity:

1.   Right-click between the second IfElse branch (Figure 2.11) and the right border of the IfElse activity and select Add Branch from the drop-down.

FIGURE 2.11 Add a third branch to an IfElse activity.

Add a third branch to an IfElse activity.

2.   Drag (move) the Code activity from the middle IfElse branch to the newly added third branch.

3.   Rename the second branch ApprovalRequired and the third branch CreditFailed. The workflow should now appear like Figure 2.12:

FIGURE 2.12 Workflow with IfElse activity with the third branch.

Workflow with IfElse activity with the third branch.

4.   Drag and drop a (new) Code activity and insert it in the second branch.

5.   Double-click the new Code activity and add the following snippet to its handler:

     // Case the sender object to a codeactivity
     CodeActivity ca = sender as CodeActivity;

     // Print the code activity name
     Console.WriteLine
    ("Additional approval required: {0} executed in the middle branch"
                  , ca.Name);

Creating the Declarative Rule

Let’s go though the next steps to create a Declarative Rule Condition.

1.   Click the red exclamation mark, and then click Property ‘Condition’ Is Not Set. You will now be in the Condition property, ready to input a rule to determine whether this IfElseBranch should execute.

2.   Click the drop-down in the Condition property and select Declarative Rule Condition.

3.   Click the + at the left of the Condition property, enter DeclarativeRuleCondition in the ConditionName property, and press Enter.

4.   Click the ellipses button in the ConditionName property and click the Edit button.

5.   Enter this.Amount < 2000 into the Rule Condition Editor.

6.   You should have the following dialog with the expression you entered in it (see Figure 2.13):

FIGURE 2.13 Declarative Rule editor.

Declarative Rule editor.

7.   Click the OK button twice to save your Declarative Rule and exit both dialogs.

8.   Change the Amount in the Dictionary Object in Program.cs to 1200 and run the workflow.

9.   You should now see that additional approval is required because the amount is more than 1,000 and less than 2,000, as shown in Figure 2.14.

FIGURE 2.14 Additional approval results.

Additional approval results.

10.   Double-click the .rules file in the Solution Explorer below workflow1.cs. (Expand workflow1.cs, if necessary.)

11.   The Declarative Rule you entered is shown in Figure 2.15. It is based on a combination of the CodeDom (.NET code serialization technology) and XML, so it is very verbose. However, you do not need to look at this file very often. It is meant for tools to execute and analyze.

FIGURE 2.15 Declarative rules (.rules file) serialization format.

Declarative rules (.rules file) serialization format.

Image

The next logical step is to add the logic to require approval when the middle branch (approval required) is executed. This, however, requires in-flight workflow access. You will see examples of how to accomplish this when you work with more advanced host-workflow data exchange techniques, which you will do beginning with Hour 5, “Creating an Escalation Workflow.”

Examining the Project Files

We used the default Workflow1.cs created by the sequential workflow project template. This generates what is known as a code-only workflow, which means that the controls added to the workflow are contained in a partial class with a designer.cs extension. These controls are loaded in the .cs portion of the class by a call to InitializeComponent in the constructor. This is exactly how a Windows Form is structured. In the next steps, you will walk through the project structure for a project that contains one code-only workflow.

1.   Right-click Workflow1.cs in the Solution Explorer and choose View Code, which contains the code-beside logic. It is a partial class that augments the workflow and contains the code written in this lab.

2.   Double-click Workflow1.designer.cs in the Solution Explorer to open it and click the + next to the Designer Generated Code region. Workflow1.designer.cs is also a partial class (the other half of the Workflow1 class) that contains the activities added to the workflow. This file is the programmatic representation of the graphical display contained in the workflow designer.

3.   For instance, Listing 2.2 contains the code in Workflow1.designer.cs that adds a Code activity to the workflow:

LISTING 2.2 Add a Code Activity in Code


     private void InitializeComponent( )
     {
       // other code
       this.codeActivity2 = new System.Workflow.Activities.CodeActivity( );
       this.codeActivity2.Name = "codeActivity2";
       this.codeActivity2.ExecuteCode +=
       new System.EventHandler(this.codeActivity2_ExecuteCode);

       // it is then added to the IfElse activity that is
       // added to the workflow
       // remmaining code
     }


4.   Program.cs represents the host in this example. In most cases the host will be another application because a console application isn’t generally a useful place to have long running workflows.

5.   As you’ve already seen, a .rules file is created when declarative rules are used, which is completely independent of the type of workflow.

If you prefer you can create the workflow via code. Whether created in code or graphically, the code and designer should remain synchronized, although this is not always the case. Therefore, be prepared to lose the ability to view your workflow if you create it programatically.

Creating a XAML + Code Workflow

The default option is to create a code-only workflow. In this section you learn to add a XAML + code workflow. This will store the workflow activities in XAML, and the code-beside remains in code. The advantage to this route is that the workflows themselves are more accessible by tools. However, there are no real compilation advantages to this option versus its code-only compatriot; both must be compiled.

Adding and Configuring Activities

The next steps walk you through creating a XAML + Code workflow.

1.   Right-click FirstWorkflowProject in the Solution Explorer and choose Add, New Item.

2.   Select Workflow in the left pane and select the Sequential Workflow (with code separation) item template.

3.   Enter Workflow2XOMLandCode.xoml into the Name dialog box and click the Add button.

4.   You should now have an empty workflow designer form.

5.   Drag and drop a Code activity, Delay activity, and another Code activity onto the workflow, in that order.

6.   Double-click the first Code activity to open its handler and enter the following:

        Console.WriteLine("In the first code activity.");

7.   Open Workflow2XOMLandCode in design mode. Then double-click the second Code activity to open its handler and enter the following (be careful to go back to the workflow designer for the new workflow):

     Console.WriteLine("In the second code activity.");

8.   Open Workflow2XOMLandCode in design mode. Change the TimeoutDuration on the Delay activity to 00:00:10 seconds.

9.   Your workflow should now look like Figure 2.16:

FIGURE 2.16 Workflow2XOMLandCode workflow.

Workflow2XOMLandCode workflow.

Examining the XAML Workflow

Let’s take a look at the XAML workflow in the following steps.

1.   Save the project by selecting File, Save All.

2.   Open Workflow2XOMLandCode.xoml in the XML editor by right-clicking it, selecting Open With, XML Editor, and pressing OK. (Click Yes to dialogs that warn that files are open and request that you save, if you did not click Save, All in the previous step.)

3.   The workflow is now expressed in XAML as shown:

<SequentialWorkflowActivity
x:Class="FirstWorkflowProject.Workflow2XOMLandCode"
x:Name="Workflow2XOMLandCode"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
    <CodeActivity x:Name="codeActivity1"
ExecuteCode="codeActivity1_ExecuteCode" />
    <DelayActivity TimeoutDuration="00:00:10" x:Name="delayActivity1" />
    <CodeActivity x:Name="codeActivity2"
ExecuteCode="codeActivity2_ExecuteCode" />
</SequentialWorkflowActivity>

The file Workflow2XOMLandCode.xoml would be named Workflow2XOMLandCode.designer.cs if this was a code-only workflow. The workflow model is now represented in this XAML file rather than in the constructor of a .designer.cs file. The x:Class="FirstWorklfowProject.Workflow2XOMLandCode" points to the code-beside class that supporrs the workflow expressed in XAML.

Image

As explained in Hour 1, “Understanding Windows Workflow Foundation,” the contents of .xoml files are standard XAML; .xoml is used so that browsers will not attempt to render it.

Running the XAML + Code Workflow

XAML + code workflows are compiled as if they were code-only workflows. Therefore, the syntax to load and execute them is identical to that of a code-only workflow. The only change in this section is that you will point the host to Workflow2XOMLandCode instead of Workflow1 in the next steps.

1.   Change the host program to point to the new workflow by replacing the current line that instantiates the workflow instance (the one that starts with WorkflowInstance instance =) with the code shown next:

     WorkflowInstance instance =
        workflowRuntime.CreateWorkflow
        (typeof(FirstWorkflowProject. Workflow2XOMLandCode));

2.   Run the workflow and you will see the results shown in Figure 2.17. It runs as if it was created entirely in code. There is no difference from an execution standpoint.

FIGURE 2.17 XOML plus code workflow results.

XOML plus code workflow results.

Creating a XAML-Only Workflow

We will create a XAML-only version of our workflow in this task. Unlike its predecessors, limitations exist to XAML-only workflows. They do not support code very well. Therefore, they do not support Code activities because they do not have a code-beside file where code can be stored.

If XAML-only workflows are limited, why use them? They can run without compilation. This enables all sorts of scenarios ranging from business analyst-friendly workflow designers to retrieving workflows from a database. The SharePoint Designer featured in SharePoint workflow exemplifies a business analyst-friendly designer that allows workflows to be created and run without compilation.

There are two ways to work around the fact that XAML workflows do not allow code. One is to create custom activities (described in Hours 20 to 24) that contain the custom code in ready-to-use activities. This is one of WF’s major features. The other is to embed the code directly in the XAML, which is not a great option because it requires compilation.

Creating XAML-only workflows does require a few additional steps.

Modeling and Preparing the XAML-Only Workflow for Execution

In the next steps, you will now create a new workflow using the same code separation template. You will then manually modify it to be a XAML-only workflow. The main change you will make is to remove the pointer the code-beside class used in XAML plus code workflows. This class is neither needed nor allowed in XAML-only workflows. You will also configure the XAML file to not be compiled and to be copied to the bindebug directory.

1.   Right-click FirstWorkflowProject in the Solution Explorer and choose Add, New Item.

2.   Select Workflow in the left pane and select the Sequential Workflow (with code separation) item template.

3.   Enter Workflow2XOMLOnly.xoml into the Name dialog and click the Add button.

      You should now have an empty workflow designer form.

4.   Add a Delay activity to the workflow.

5.   Save the project by selecting File, Save All.

6.   Open Workflow2XOMLOnly.xoml in the XML editor by right-clicking it, selecting Open With, XML Editor, and clicking OK. (Click Yes to dialogs that warn that files are open and request that you save, if you did not Save, All in the last step.)

7.   Remove the line that points to the code-beside class x:Class="FirstWorkflowProject. Workflow2XOMLOnly and save the project again.

8.   Select Workflow2XOMLOnly.xoml in Solution Explorer and change its Copy to Output property to Copy If Newer and its Build Action property to None.

9.   Build the project. Make sure it builds successfully and verify that the Workflow2XOMLOnly.xoml file was copied to the C:SamsWf24hrsHoursHour02ASpinAroundWFFirstWorkflowProjectFirstWorkflowProjectinDebug directory.

Call XAML-Only Workflow from Host

You will now load the XAML workflow as an XML document in the next steps. WF will load and execute the activities on the workflow without a separate compilation step. The workflow is currently started by passing a .NET type to the WorkflowRuntime.CreateWorkflow method. You will create a text reader that contains the XOML workflow information and then pass it to the CreateWorkflow method.

1.   Open Program.cs and replace the line of code that starts with WorkflowInstance instance = WorkflowRuntime.CreateWorkflow with the following two lines of code to create the XML text reader and pass it to the CreateWorkflow method:

                XmlTextReader xmltr = new XmlTextReader(@
"C:SamsWf24hrsHoursHour02ASpinAroundWFFirstWorkflowProjectFirstWorkflo
wProjectinDebugWorkflow2XOMLOnly.xoml");
                WorkflowInstance instance =
workflowRuntime.CreateWorkflow(xmltr);

2.   Add the following using directive below the other using statement at the top of the file:

using System.Xml;

3.   Run the workflow. The only results you will see are the host requesting that you press any key after the delay.

Image

This example is obviously contrived. The XAML-only workflow option is useful only in conjunction with custom activities of which there must be enough to create a workflow without code. For example, if there were Customer, Credit, and other activities, it would be possible to create a credit process workflow with the combination of BAL and these custom activities that did not require code. In this case, XAML-only workflows are attractive. As mentioned already, the SharePoint Designer uses XAML-only workflows to allow knowledge workers to create workflows without compilation, and they can create reasonably functional workflows that contain multiple levels of escalation and dynamic task assignment, among other features.

XAML-only workflows cannot receive parameters via a Dictionary Object and cannot have constructors. There are other items you should know if you’re working with moderate-to-complex XAML workflows. These topics are not covered in this book. I recommend looking at this blog entry if you want to learn more about XAML-only workflows: http://blogs.msdn.com/endpoint/archive/2008/07/06/download-posted-wf-xaml-workshop.aspx.

Going forward, it is likely there will be better all-around XAML support in WF because its ability to execute without compilation and the ability for tools to access it are key to WF’s vision.

Summary

This hour featured a walk through a wide range of basic WF functionality. It covered everything from project structure, to rules, to XAML-only workflows. It built on the conceptual walkthrough and installation provided in Hour 1, “Understanding Windows Workflow Foundation.” You need to learn a little more about hosting, which you will do in Hour 3, “Learning Basic Hosting.” After that, you are ready to build on what you learned here and create workflows that manage long-running state, approval scenarios, and escalation.

Workshop

Quiz

1.

What is the advantage of declarative rules over code-based rules?

2.

How many types of workflows are there in WF?

3.

What are the advantages of XAML-only workflows?

4.

How do you debug a WF workflow?

5.

Can code activities be used on XAML-only workflows?

6.

Does the IfElse activity execute every branch that evaluates to true or only the first one that evaluates to true?

7.

Passing a dictionary object as a parameter to workflows is simple. What limitations does it carry?

Answers

1.

Tooling support, and they can be changed without requiring recompilation.

2.

Three: Code only, XAML + Code, and XAML only.

3.

Tooling, and they can be executed without compilation. They provide for powerful options when retrieved dynamically from a database.

4.

Right-click an activity and select Insert Breakpoint, or set the breakpoint in code, as would be done in any other .NET application.

5.

No, they always have code to execute, and code cannot be executed on XAML-only workflows.

6.

Just the first one.

7.

It cannot be used to interact with workflows in-flight and is therefore not useful as the sole workflow-host interaction method for workflows that require escalation and other typical workflow actions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.75.221