Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Microsoft Windows Workflow Foundation 4.0 Cookbook
Microsoft Windows Workflow Foundation 4.0 Cookbook

Microsoft Windows Workflow Foundation 4.0 Cookbook: Get the flexibility of Windows Workflow Foundation working for you. Based on a cookbook approach, this guide takes you through all the essential concepts with recipes you can apply or adapt to your own specific needs.

By Andrew Zhu
€32.99 €22.99
Book Sep 2010 272 pages 1st Edition
eBook
€32.99 €22.99
Print
€41.99
Subscription
€14.99 Monthly
eBook
€32.99 €22.99
Print
€41.99
Subscription
€14.99 Monthly

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Sep 24, 2010
Length 272 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781849680783
Vendor :
Microsoft
Category :
Table of content icon View table of contents Preview book icon Preview Book

Microsoft Windows Workflow Foundation 4.0 Cookbook

Chapter 1. Workflow Program

In this chapter, we will cover:

  • Creating the first WF program: HelloWorkflow

  • Creating a WF program using C# code

  • Initializing a WF program using InArguments

  • Creating a WF program using OutArgument

  • Creating a WF Program using InOutArgument

  • Using Variable in a WF program

  • Running a WF program asynchronously

  • Customizing a MyReadLine activity with Bookmark

  • Converting a WF program instance to XAML

  • Loading up a WF program from an XAML file

  • Testing a WF program with a unit test framework

  • Debugging a WF program

Introduction


Considering workflow programs as imperative programs, we need to think of three fundamental things:

  • How to define workflow programs

  • How to build (compile) workflow programs

  • How to execute workflow programs

In WF4, we can define a workflow in either managed .NET code or in XAML. There are two kinds of code workflow authoring styles:

  • Creating a Custom Activity class

  • Creating workflow dynamically in the runtime

There are also two ways to author workflow in XAML:

  • By WF designer (recommended)

  • Typing XML tags manually

Essentially, a workflow program is a .NET program, no matter how we create it.

After defining workflows, we can build workflow applications as we build normal .NET applications.

When it comes to workflow execution, we need to consider three basic things:

  • How to flow data into and out of a workflow

  • How to store temporary data when a workflow is executing

  • How to manipulate data in a workflow

This chapter is going to focus on answering these questions.

Before moving ahead, make sure we have the following installed on our computer:

  • Windows Vista/7 or Windows Server 2008

  • Visual Studio 2010 and .NET framework 4.0

We can also use Windows XP; however, its usage is not recommended.

Creating the first WF program: HelloWorkflow


In this task we will create our first workflow to print "Hello Workflow" to the console application.

How to do it...

  1. Create a Workflow Console Application project:

    After starting Visual Studio 2010, select File | New Project. A dialog is presented, as shown in the following screenshot. Under the Visual C# section, select Workflow, and choose Workflow Console Application. Name the project HelloWorkflow. Name the solution Chapter01 and make sure to create a directory for the solution.

  2. Author the workflow program:

    First, drag a Sequence activity to the designer from Toolbox, next drag a WriteLine activity into the Sequence activity. Finally, input "Hello Workflow" in the expression box of the WriteLine activity. We can see in the following screenshot:

  3. Run it:

    Press Ctrl+F5 to run the project without debugging. The result is as shown in the following screenshot:

How it works...

When we press Ctrl+F5, Visual Studio saves the current project, and then it runs the project from the Main method in the Program.cs file.

WorkflowInvoker.Invoke(new Workflow1());

The preceding statement starts the workflow. After the workflow starts running, the WriteLine activity prints the "Hello Workflow" to the Console Application.

The workflow we created in WF Designer is actually an XML file. We can open Workflow1.xaml with an XML editor to check it.

Tip

Right-click on Workflow1.xaml then click Open With…, and choose XML Editor to open Workflow1.xaml as an XML file.

All XAML files will be compiled to .dll or .exe files. That is why when we press Ctrl+F5, the program just runs like a normal C# program.

There's more...

So far, there are no officially published WF4 Designer add-ins for Visual Studio 2008. We need a copy of Visual Studio 2010 installed on our computer to use WF4 Designer, otherwise we can only create workflows by imperative code or by writing pure XAML files.

Creating a WF program using C# Code


In this task, we will create the same "HelloWorkflow" function workflow using pure C# code, beginning from a Console Application.

How to do it...

  1. Create a Console Application project:

    Create a new Console Application project under the Chapter01 solution. Name the project HelloCodeWorkflow. The following screenshot shows the Console Application new project dialog:

  2. Add reference to the System.Activities assembly:

    By default, a new Console Application doesn't have reference to the System.Activities assembly, due to which we need to perform this step.

  3. Create workflow definition code:

    Open Program.cs file and change the code present as follows:

    using System.Activities;
    using System.Activities.Statements;
    
    namespace HelloCodeWorkflow {
        class Program {
            static void Main(string[] args) {
                WorkflowInvoker.Invoke(new HelloWorkflow());
            }
        }
    
        public class HelloWorkflow:Activity {
            public HelloWorkflow() {
                this.Implementation = () => new Sequence {
                    Activities = {
                        new WriteLine(){Text="Hello Workflow"}
                    }
                };
            }
        }
    }
    
  4. Run it:

    Set HelloCodeWorkflow as StartUp project and press Ctrl+F5 to run it. As expected, the result should be just like the previous result shown.

How it works...

We use the following namespaces:

using System.Activities;
using System.Activities.Statements;

Because WorflowInvoker class belongs to System.Activities namespace. Sequence activity, WriteLine activity belongs to System.Activities.Statements. namespace.

public class HelloWorkflow:Activity {
    public HelloWorkflow() {
        this.Implementation = () => new Sequence {
            Activities = {
                new WriteLine(){Text="Hellow Workflow"}
            }
        };
    }
}

By implementing a class inherited from Activity, we define a workflow using imperative code.

WorkflowInvoker.Invoke(s);

This code statement loads a workflow instance up and runs it automatically. The WorkflowInvoker.Invoke method is synchronous and invokes the workflow on the same thread as the caller.

There's more

WF4 also provides us a class DynamicActivity by which we can create a workflow instance dynamically in the runtime. In other words, by using DynamicActivity, there is no need to define a workflow class before initializing a workflow instance. Here is some sample code:

public static DynamicActivity GetWF() {
    return new DynamicActivity() {
        Implementation = () => new Sequence() {
            Activities ={
                new WriteLine(){Text="Hello Workflow"}
            }
        }
    };
}

Initializing a WF program using InArguments


In this task, we will create a WF program that accepts arguments when initialized in the WF host. In WF4, we can use InArguments to define the way data flows into an activity.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution. Name the project UseInArgument .

  2. Author the WF program:

    Create a workflow as shown in the following screenshot:

  3. Write code to host the workflow.

    Open the Program.cs file and change the host code as follows:

    using System.Activities;
    using System.Activities.Statements;
    
    namespace UseInArgument {
    class Program {
            static void Main(string[] args) {
                WorkflowInvoker.Invoke(new Workflow1() 
                {
                    FirstName="Andrew",
                    SecondName="Zhu"
                });
            }
        }
    }
  4. Run it:

    Set UseInArgument as StartUp project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the following message:

How it works...

Consider the following statement from the code we saw in the preceding section:

FirstName="Andrew"

FirstName is an InArgument type, but how can we assign a string to InArgument without any explicit cast? This is because InArgument is declared with an attribute System.ComponentModel.TypeConverterAttribute(System.Activities.XamlIntegration.InArgumentConverter). The class inheritance is shown in the following diagram:

It is the InArgumentConverter that makes assigning a string to an InArgument possible. If we want to know more about TypeConverter, we can check MSDN the reference at http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx

There's more

In WF3/3.5, we can pass values to Workflow wrapped in a Dictionary<T> object. This also applies to WF4.

using System.Activities;
using System.Activities.Statements;
using System.Collections.Generic;

namespace UseInArgument {
    class Program {
        static void Main(string[] args) {
            IDictionary<string, object> inputDictionary = 
                new Dictionary<string, object>() 
            { 
                {"FirstName","Andrew"},
                {"SecondName","Zhu"}
            };
            WorkflowInvoker.Invoke(new Workflow1(), 
                                   inputDictionary);
        }
    }
}

If we are creating workflows using imperative code, we can use InArgument in the following way:

public class WorkflowInCode:Activity {
    public InArgument<string> FirstName { get; set; }
    public InArgument<string> SecondName { get; set; }
    public WorkflowInCode() {
        this.Implementation = () => new Sequence() {
            Activities = {
                new WriteLine(){
                    Text=new InArgument<string>(
                            activityContext=>"My name is "+FirstName.Get(activityContext)
                        )
                },
                new WriteLine(){
                    Text=new InArgument<string>(
                            ActivityContext=>SecondName.Get(ActivityContext)
                        )
                }
            }
        };
    }
}

Creating a WF program using OutArgument


In this task, we will create a WF program that can return a result to the workflow host.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution; name the project as UseOutArgument.

  2. Author a workflow:

    Author the workflow shown in the following screenshot. Here are the detailed actions:

    1. Drag a Sequence activity from Toolbox to the designer panel.

    2. In the bottom of the designer panel, click the Arguments button, and click Create Argument to create an OutArgument string named OutMessage.

    3. Drag two WriteLine activities from Toolbox into the Sequence activity and fill the textboxes with "Start…" and "End" respectively.

    4. Drag an Assign activity from Toolbox to the designer panel. Fill the right expression box with OutArgument as OutMessage, whereas fill the right expression box with the following string: This is a message from workflow.

  3. Write code to host the workflow:

    Open Program.cs file and change the host code as follows:

    using System;
    using System.Activities;
    using System.Collections.Generic;
    
    namespace UseOutArgument {
        class Program {
            static void Main(string[] args) {
                IDictionary<string,object> output=
                    WorkflowInvoker.Invoke(new Workflow1());
                Console.WriteLine(output["OutMessage"]);
            }
        }
    }
    
  4. Run it:

    Set UseOutArgument as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the message as shown in the next screenshot:

How it works...

Look at the following code snippet:

IDictionary<string,object> output=
     WorkflowInvoker.Invoke(new Workflow1());
Console.WriteLine(output["OutMessage"]);

OutMessage is the name of OutArgument we defined in Workflow1.xaml. the WorkflowInvoder.Invoke method will return a IDictionary type object.

There's more...

There is a third type of workflow argument: InOutArgument. It is a binding terminal that represents the flow of data into and out of an activity. In most cases, we can use InOutArgument instead of InArgument and OutArgument. But there are still some differences—for example, we cannot assign a string to InOutArgument, while it is allowed to assign a string to InArgument directly in the host program.

Creating a WF program using InOutArgument


In this task, we will create a WF program using InOutArgument. This type of argument is used to receive values and is also used to pass values out to the caller (WF host).

How to do it…

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution and name the project as UseInOutArgument.

  2. Author a workflow:

    Create an InOutArgument type argument: InOutMessage. Author a WF program as shown in the following screenshot. In the Assign activity textbox, type InOutMessage = "Now, I am an OutMessage".

  3. Write code to host the workflow:

    Open the Program.cs file and alter the code as shown:

    using System;
    using System.Activities;
    using System.Activities.Statements;
    using System.Collections.Generic;
    
    namespace UseInOutArgument{
        class Program{
            static void Main(string[] args){
                IDictionary<string, object> input =
                    new Dictionary<string, object>() 
                { 
                    {"InOutMessage","Now, I am InMessage"}
                };
                IDictionary<string,object> output=
                    WorkflowInvoker.Invoke(new Workflow1(),input);
                Console.WriteLine(output["InOutMessage"]);
            }
        }
    }
    
  4. Run it:

    Set UseInOutArgument as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the message as shown in the following screenshot:

How it works...

The following code block initializes the InArgument value:

IDictionary<string, object> input =
                new Dictionary<string, object>() 
            { 
                {"InOutMessage","Now, I am InMessage"}
            };

This statement will run the workflow program with the input dictionary.

IDictionary<string,object> output=
                WorkflowInvoker.Invoke(new Workflow1(),input);

The string Now, I am InMessage is printed by the workflow. The string Now, I am an OutMessage is a message altered in the workflow and passed to the host and then printed by the host program.

There's more...

We cannot assign a string to InOutArgument directly, and the following style of parameter initialization is not allowed:

IDictionary<string, object> output =
    WorkflowInvoker.Invoke(new Workflow1() 
    { 
        InOutMessage="Now,I am InMessage"
    });

See Also

  • Creating a WF program using OutArgument

  • Initializing a WF program using InArguments

Using Variable in a WF program


We can use Variable temporarily to store a value when a WF program is running. In this task, we will create a WF program that prints five numbers to the console in a loop. We will use the NumberCounter variable as a number counter.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution and name the project as UseVariable.

  2. Author a workflow:

    Add a Sequence activity, click the Sequence activity, create an Int32 NumberCounter variable, and set its Scope to Sequence. Then, author the workflow as shown in the following screenshot. In the second Assign activity type NumberCounter=NumberCounter+1.

  3. Run it:

    Set UseVariable as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the following message:

How it works...

To make the workflow logic easy to understand, translate the workflow into C# code. It will look like:

int NumberCounter = 0;
do 
{
    Console.WriteLine(NumberCounter);
    NumberCounter++;
}while (NumberCounter <= 5);

While we can use arguments to flow data into and out of a workflow, we use Variable to store data in a workflow. Every variable has its scope, and can be accessed by activities within its scope. Variable in WF4 is pretty much like variables in imperative language such as C#.

There's more...

Please note that we cannot access to the workflow variables from the outside host. WF4 variables are designed for sharing data inside the workflow instance. We can use Bookmark to access the workflow from the outside host.

See Also

  • Customizing a MyReadLine activity with Bookmark

Running a WF program asynchronously


In the previous tasks, we used the WorkflowInvoker.Invoke method to start a workflow instance on the same thread as the main program. It is easy to use; however, in most real applications, a workflow should run on an independent thread. In this task, we will use WorkflowApplication to run a workflow instance.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution and name the project as UseWorkflowApplication.

  2. Author a workflow:

    In the opening Workflow1.xaml designer, click on Arguments, create two Int32 InArguments for Number1 and Number2. Create an Int32 OutArgument for Result. Add an Assign activity to the workflow designer panel. In the Assign activity, type Result=Number1+Number2.

  3. Write code to host the workflow:

    Open Program.cs file and change code as follow:

    using System;
    using System.Activities;
    using System.Activities.Statements;
    using System.Threading;
    using System.Collections.Generic;
    
    namespace UseWorkflowApplication{
        class Program{
            static void Main(string[] args){
                AutoResetEvent syncEvent = 
                   new AutoResetEvent(false);
                IDictionary<string, object> input = 
                   new Dictionary<string, object>()
                {
                    {"Number1",123},
                    {"Number2",456}
                };
                IDictionary<string,object> output=null;
                WorkflowApplication wfApp = 
                   new WorkflowApplication(new Workflow1(),input);
                wfApp.Completed = 
                delegate(WorkflowApplicationCompletedEventArgs e)
                {
                    Console.WriteLine("Workflow thread id:"+
                            Thread.CurrentThread.ManagedThreadId);
                    output = e.Outputs;
                    syncEvent.Set();
                };
                wfApp.Run();
                syncEvent.WaitOne();
                Console.WriteLine(output["Result"].ToString());
                Console.WriteLine("Host thread  id:"+Thread.CurrentThread.ManagedThreadId);
            }
        }
    }
  4. Run it:

    Set UseWorkflowApplication as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the following message:

How it works...

The function of this workflow is adding two InArgument Numbers and assigning the result to an OutArgument Result.

AutoResetEvent syncEvent = new AutoResetEvent(false);

As the workflow thread runs simultaneously with the caller thread, the caller thread may terminate before the workflow thread. To prevent this unexpected program quit, we need to use AutoResetEvent to synchronize caller and workflow thread.

syncEvent.WaitOne();

The caller thread will wait there, until syncEvent is set.

wfApp.Completed = 
delegate(WorkflowApplicationCompletedEventArgs e)
{
   output = e.Outputs;
   syncEvent.Set();
};

When the workflow completes, syncEvent.Set() is invoked. After that, the caller can continue running to its end.

Another thing we should be aware of is how we get the result when the workflow ends. Unlike the WorkflowInvoker.Invoker method, in a WorkflowApplication-style caller, we get dictionary output from WorkflowApplicationCompletedEventArgs's Outputs property; see the preceding code snippet.

Customizing a MyReadLine activity with Bookmark


By using InArgument, OutArgument, and InOutArgument, we can flow data into the workflow when it starts and out of the workflow when it ends. But how can we pass data from the caller into the workflow when it is executing?—Bookmark will help us to do this. In this task, we will create a MyReadLine activity using a bookmark.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution and name the project as UseBookmark. Next, add a code file to this project and name the file as MyReadLineActivity. We can see this in the following screenshot:

  2. Customize the activity with Bookmark:

    Fill the opening MyReadLineActivity.cs file with the following code:

    using System.Activities;
    namespace UseBookmark{
        public class MyReadLine : NativeActivity<string>{
            [RequiredArgument]
            public InArgument<string> BookmarkName { get; set; }
            protected override void Execute(
                NativeActivityContext context)
            {
                context.CreateBookmark(BookmarkName.Get(context),
                         new BookmarkCallback(OnResumeBookmark));
            }
            protected override bool CanInduceIdle
            {
                get
                {
                    { return true;}
                }
            }
            public void OnResumeBookmark(
                NativeActivityContext context,
                Bookmark bookmark,
                object obj)
            {
                Result.Set(context, (string)obj);
            }
        }
    }
    

    Save the file and press F6 to build the project so that the activity will appear in the WF designer activity toolbox.

  3. Author a workflow:

    Open Workflow1.xaml and author the workflow as shown in the following screenshot:

  4. Write code to host the workflow:

    Open Program.csfile and change the code as follows:

    using System;
    using System.Linq;
    using System.Activities;
    using System.Activities.Statements;
    using System.Threading;
    
    namespace UseBookmark{
        class Program{
            static void Main(string[] args)
            {
                AutoResetEvent syncEvent = 
                    new AutoResetEvent(false);
                string bookmarkName="GreetingBookmark";
                WorkflowApplication wfApp = 
                    new WorkflowApplication(new Workflow1()
                {
                    BookmarkNameInArg=bookmarkName
                });
                wfApp.Completed = delegate(
                    WorkflowApplicationCompletedEventArgs e)
                {
                    syncEvent.Set();
                };
                wfApp.Run();
                wfApp.ResumeBookmark(bookmarkName, 
                    Console.ReadLine());
                syncEvent.WaitOne();
            }
        }
    }
    
  5. Run it:

    Set UseBookmark as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the message as shown in the following screenshot:

How it works...

In the code shown in the second step, we create a class inherited from NativeActivity. NativeActivity is a special abstract activity that can be used to customize complex activities; we will talk about it more in Chapter 5, Custom Activities.

context.CreateBookmark(BookmarkName.Get(context),
        new BookmarkCallback(OnResumeBookmark));

By this statement, the WF context creates a Bookmark with arguments BookMarkName and BookMarkCallback. When the wfApp.ResumeBookmark method is called, the OnResumeBookmark that was defined in the Customized Activity body will be executed.

protected override bool CanInduceIdle{
    get
    {
        { return true;}
    }
}

This is a built-in property that indicates whether the customized activity can cause the workflow to become idle; the default value is false.

Consider the following code snippet of step 3:

wfApp.ResumeBookmark(bookmarkName, 
                Console.ReadLine());

When this statement is executed, the OnResumeBookmark method defined in the MyReadLine activity will be called and the method will accept the value passed via Console.ReadLine().

Converting a WF program instance to XAML


In real applications, we would like to write and test WF programs in imperative code, while storing, running, and transmitting workflow as an XAML string or file. In this task, we will convert a WF program instance to an XAML string.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution and name the project ConvertWFInstanceToXML. Delete the Workflow1.xaml file that is created by default.

  2. Write code to create the workflow and its host:

    Open Program.cs file and change the code as follows:

    using System;
    using System.Activities;
    using System.Activities.Statements;
    using System.Text;
    using System.Xaml;
    using System.Activities.XamlIntegration;
    using System.IO;
    
    namespace ConvertWFObjectToXML {
        class Program {
            static void Main(string[] args) {
                //Create a Workflow instance object
            ActivityBuilder ab = new ActivityBuilder();
                ab.Implementation = new Sequence() 
                {
                    Activities =
                    {
                        new WriteLine{Text="Message from Workflow"}
                    }
                };
    
                //Convert Workflow instance to xml string
                StringBuilder sb = new StringBuilder();
                StringWriter sw = new StringWriter(sb);
                XamlWriter xw = 
                    ActivityXamlServices.CreateBuilderWriter(
                    new XamlXmlWriter(sw, 
                                      new XamlSchemaContext()));
                XamlServices.Save(xw, ab);
                Console.WriteLine(sb.ToString());
            }
        }
    }
  3. Run it:

    Set ConvertWFInstanceToXML as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the message as shown in the following screenshot:

Consider the following XML string reformatted from the screenshot:

<?xml version="1.0" encoding="utf-16"?>
<Activity  x:Class="{x:Null}" 
                  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" 
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
       <Sequence>
            <WriteLine Text="Hello" />
       </Sequence>
</Activity>

How it works...

Consider the following code line:

XamlServices.Save(xw, ab);

XamlServices provides services for the common XAML tasks of reading XAML and writing an object graph, or reading an object and writing out an XAML file. This statement reads an ActivityBuilder object and writes XAML to an XamlWriter object.

We use ActivityBuilder as an activity wrapper so that the output XAML is a loadable workflow. In other words, if we save, say, a Sequence activity to an XamlWriter directly, then the output XML workflow will be unloadable for further use.

Loading up a WF program from an XAML file


In this task, we will run a WF program by loading it from an XAML file.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application under the Chapter01 solution and name the project as LoadUpWorkflowFromXML.

  2. Author a workflow:

    Author the Workflow1.xaml file; this workflow will print a string to console as shown in the following screenshot:

  3. Create code to load up the workflow instance from an XAML string:

    Open Program.cs file and change code as follow:

    using System;
    using System.Activities;
    using System.Activities.Statements;
    using System.IO;
    using System.Collections;
    using System.Text;
    using System.Activities.XamlIntegration;
    
    namespace LoadUpWorkflowFromXML {
        class Program {
            static void Main(string[] args) {
                string filePath=           @"C:\WF4Cookbook\Chapter01\LoadUpWFFromXML\Workflow1.xaml";
                string tempString="";
                StringBuilder xamlWFString = new StringBuilder();
                StreamReader xamlStreamReader = 
                    new StreamReader(filePath);
                while (tempString != null){
                    tempString = xamlStreamReader.ReadLine();
                    if (tempString != null) {
                        xamlWFString.Append(tempString);
                    }
                }
                Activity wfInstance = ActivityXamlServices.Load(
                    new StringReader(xamlWFString.ToString()));
                WorkflowInvoker.Invoke(wfInstance);
            }
        }
    }
    

    Tip

    We may need to change the file path according to our real environment.

  4. Run it:

    Set LoadUpWorkflowFromXML as Startup project. Press Ctrl+F5 to build and run the workflow without debugging. The application should run in a console window and print the message as shown in the following screenshot:

How it works...

We use the following code block to read a workflow XML string from file and store the string in xamlWFString:

string filePath=           @"C:\WF4Cookbook\Chapter01\LoadUpWFFromXML\Workflow1.xaml";
string tempString="";
StringBuilder xamlWFString = new StringBuilder();
StreamReader xamlStreamReader = 
new StreamReader(filePath);
while (tempString != null)
{
    tempString = xamlStreamReader.ReadLine();
    if (tempString != null) 
    {
        xamlWFString.Append(tempString);
    }
}

Then, using the following statement, ActivityXamlServices reads the XML workflow and builds up a workflow object graph:

Activity wfInstance = ActivityXamlServices.Load(
                new StringReader(xamlWFString.ToString()));

Testing a WF program with a unit test framework


In this task, we will create a Test Project to do unit testing for a WF program.

How to do it...

  1. Add a Test Project to the solution:

    Add a Test Project to the Chapter01 solution and name the project as UnitTestForWFProgram as shown in the following screenshot:

  2. Add a workflow file to the Test Project:

    Add a workflow activity to this project. Right-click the newly created Test Project, then go to Add | New Items… | Workflow | Activity and name the activity as WorkflowForTest.xaml. In the opening WF designer, create an OutArgument as OutMessage. Next, drag an Assign activity to the Designer panel and assign the string "Test Message" to the OutMessage argument as shown in the following screenshot:

    Tip

    In WF4, workflow is actually an Activity class. We could see "Workflow" as a conception from a macroeconomic viewpoint, while considering "Activity" as a development concept.

  3. Create unit test code:

    Open the UnitTest1.cs file and fill the file with following code:

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Activities;
    
    namespace UnitTestForWFProgram {
        [TestClass]
        public class UnitTest1 {
            [TestMethod]
            public void TestMethod1() {
                var output = 
                    WorkflowInvoker.Invoke(new WorkflowForTest());
                Assert.AreEqual("Test Message", 
                                output["OutMessage"]);
            }
        }
    }
  4. Run it:

    Set UnitTestForWorkflow as Startup project. Press Ctrl+F5 to build and run the test without debugging as shown in the following screenshot:

How it works...

In the preceding code snippet, [TestClass] indicates it is a unit test class, whereas [TestMethod] indicates a test method. When the Test Project runs, the test method will be executed automatically.

There's more...

In real application development, we can also create a separate Unit Test project and add a reference to the target project.

Debugging a WF program


In this task, we will debug a WF program.

How to do it...

  1. Create a workflow project:

    Create a new Workflow Console Application project under the Charpter01 solution. Name the project as DebugWFProgram. In the opening WF designer panel, author a workflow as shown in the following screenshot:

  2. Create workflow host code:

    Open Program.cs file and change the code to:

    using System.Activities;
    using System.Activities.Statements;
    
    namespace DebugWFProgram{
        class Program{
            static void Main(string[] args){
                WorkflowInvoker.Invoke(new Workflow1()
                { 
                    InMessage="In Message"
                });
            }
        }
    }
    
  3. Set a debug break point:

    Right-click an activity and select Breadpoint | Insert Breakpoint to add debug break point.

  4. Debug it:

    Press F5 to debug the WF Program; we can refer the following screenshot:

There's more...

We can also debug an XAML workflow. Open Workflow with the XML editor, insert some breakpoints, then press F5; we will see the breakpoints as shown in the following screenshot:

Left arrow icon Right arrow icon

Key benefits

  • Customize Windows Workflow 4.0 applications to suit your needs
  • A hands-on guide with real-world illustrations, screenshots, and step-by-step instructions
  • Explore various functions that you can perform using WF 4.0 with running code examples
  • A hands-on guide with real-world illustrations, screenshots, and step-by-step instructions

Description

Windows Workflow Foundation 4.0 (WF) is a significant part of .NET Framework 4.0. WF makes workflow technology available to every single programmer that uses the .NET Framework 4.0. It is easy to create long running and distributed programs using WF with the right knowledge. With this book, you will discover that working with workflows is easy. This book provides both step-by-step recipes and relevant background information. It covers all the important aspects of Windows Workflow Foundation 4.0. The best thing about this book is that all recipes are based on real-world experiences of Andrew Zhu. Andrew is a global WF and BizTalk technology support engineer for Microsoft. This book covers everything you need to know, when working with workflows. Get to grips with flow control activities, messaging, and transaction processes with easy to understand steps followed by explanations. You will quickly learn to use collection and custom WF activities and WF services.You will see recipes that illustrate integration of Windows Workflow with other applications such as WPF, ASP.NET, WCF service.Lastly, you will discover how easily you can customize W4 Designer with WF rule engine and others.

What you will learn

Design and develop WF applications Control the workflow of data using arguments and variables Create a machine state style workflow using Flowchart Explore and use the built-in activities of WF Customize persistence and tracking extensions using WF Create Windows Workflow as a WCF service Host Windows Workflow in other applications (ASP.NET, WPF) Create your own independent WF Designer Tune WF applications to run steady and fast

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Sep 24, 2010
Length 272 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781849680783
Vendor :
Microsoft
Category :

Table of Contents

15 Chapters
Microsoft Windows Workflow Foundation 4.0 Cookbook Chevron down icon Chevron up icon
Credits Chevron down icon Chevron up icon
About the Author Chevron down icon Chevron up icon
About the Reviewers Chevron down icon Chevron up icon
Foreword Chevron down icon Chevron up icon
Preface Chevron down icon Chevron up icon
Workflow Program Chevron down icon Chevron up icon
Built-in Flow Control Activities Chevron down icon Chevron up icon
Messaging and Transaction Chevron down icon Chevron up icon
Manipulating Collections Chevron down icon Chevron up icon
Custom Activities Chevron down icon Chevron up icon
WF4 Extensions Chevron down icon Chevron up icon
Hosting Workflow Applications Chevron down icon Chevron up icon
Custom Workflow Designer Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Filter icon Filter
Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%

Filter reviews by


No reviews found
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.