Working with a Microsoft Windows Workflow Foundation 4.0 (WF) Program

Exclusive offer: get 50% off this eBook here
Microsoft Windows Workflow Foundation 4.0 Cookbook

Microsoft Windows Workflow Foundation 4.0 Cookbook — Save 50%

Over 70 recipes with hands-on, ready to implement solutions for authoring Microsoft Windows Workflow Foundation 4.0 workflows with this book and eBook

$29.99    $15.00
by Andrew Zhu | September 2010 | .NET Architecture & Analysis Enterprise Articles Microsoft

WF4 is a process engine, as well as a visual program language, shipped along with Microsoft .NET Framework 4.0. Traditionally, when we design a long-running application, we break a large application into lots of small code blocks to address the business logic and use a database to store the intermediate data. With the growing complexity of logic, managing code blocks and authoring logic workflows becomes difficult. Now, with WF4, we can design and create distributed, long-running programs easily.

This article by Andrew Zhu, author of Microsoft Windows Workflow Foundation 4 cookbook, provides recipes that will help us understand basic information about WF4 programming like:

  • Creating the first WF program: HelloWorkflow
  • Creating a WF program with C# code
  • Initializing a WF program with InArguments
  • Creating a WF program with OutArgument
  • Creating a WF Program with InOutArgument
  • Using variable in WF program
  • Running a WF program asynchronously
  • Customizing a MyReadLine activity with bookmark
  • Converting WF program instance to XAML
  • Loading up a WF program from a XAML file

 

Microsoft Windows Workflow Foundation 4.0 Cookbook

Microsoft Windows Workflow Foundation 4.0 Cookbook

Over 70 recipes with hands-on, ready to implement solutions for authoring workflows

  • 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

Read more about this book

(For more resources on this subject, see here.)

Introduction

Considering workflow programs as imperative program, 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:

  • 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, workflow program is .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 a temporary data when workflow is executing
  • How to manipulate data in workflow

This article 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 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 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 workflow program:
    First, drag a Sequence activity to designer from Toolbox, next drag a WriteLine activity into Sequence activity. Finally, input "Hello Workflow" in the expression box of WriteLine activity. We can see the following screenshot:

  3. Run it:
    Press Ctrl+F5 to run 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 Main method in Program.cs file.

WorkflowInvoker.Invoke(new Workflow1());

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

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

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

All XAML files will be compiled to .dll or .exe file. 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 file.

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 Chapter01 solution. Name the project HelloCodeWorkflow. The following screenshot shows the Console Application new project dialog:

  2. Add reference to System.Activities assembly:
    By default, a new Console Application doesn't have reference to 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:

    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="Hellow 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 showed.

How it works...

We use the following namespace:

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

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

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. WorkflowInvoker.Invoke method is synchronous and invokes the workflow on the same thread as the caller.

There's more

WF4 also provide 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 a sample code:

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

Microsoft Windows Workflow Foundation 4.0 Cookbook Over 70 recipes with hands-on, ready to implement solutions for authoring Microsoft Windows Workflow Foundation 4.0 workflows with this book and eBook
Published: September 2010
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Read more about this book

(For more resources on this subject, see here.)

Initializing a WF program using InArguments

In this task, we will create a WF program, which accepts arguments when initialized in 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 Chapter01 solution. Name the project UseInArgument.
  2. Author WF program:
    Create a workflow as shown in the following screenshot:

  3. Write code to host the workflow.
  4. 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"
    });
    }
    }
    }

  5. 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 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 result to the workflow host.

How to do it...

  1. Create a workflow project:
    Create a new Workflow Console Application under Chapter01 solution; name the project as UseOutArgument.
  2. Author a workflow:
    Author a workflow shown in the following screenshot. Here are the detailed actions:
    • Drag a Sequence activity from Toolbox to the designer panel.
    • In the bottom of the designer panel, click Arguments button, and click Create Argument to create an OutArgument string named OutMessage.
    • Drag two WriteLine activities from Toolbox into the Sequence activity and fill the textboxes with "Start..." and "End" respectively.
    • 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. 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 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 caller (WF host).

How to do it...

  1. Create a workflow project:
    Create a new Workflow Console Application under Chapter01 solution and name the project as UseInOutArgument.
  2. Author a workflow:
    Create an InOutArgument type argument: InOutMessage. Author WF program as shown in the following screenshot. In Assign activity textbox, type InOutMessage = "Now, I am an OutMessage".

  3. Write code to host the workflow:
    Open 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 code block initializes the InArgument value.

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

This statement will run workflow program with input dictionary.

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

There's more...

We cannot assign a string to InOutArgument directly, and the following style of parameter initializing 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 WF program

We can use Variable temporarily to store a value when WF program is running. In this task, we will create a WF program that prints five numbers to 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 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:

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 using Bookmark
Microsoft Windows Workflow Foundation 4.0 Cookbook Over 70 recipes with hands-on, ready to implement solutions for authoring Microsoft Windows Workflow Foundation 4.0 workflows with this book and eBook
Published: September 2010
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Read more about this book

(For more resources on this subject, see here.)

Running a WF program asynchronously

In the previous tasks, we used 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 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 workflow designer panel. In 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 workflow thread runs simultaneously with caller thread, 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();

Caller thread will wait there, until syncEvent is set.

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

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

Another thing we should be aware of is how we get result when workflow ends. Unlike WorkflowInvoker.Invoker method, in 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 workflow when it starts and out of the workflow when it ends. But how can we pass data from caller into 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 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 the following screenshot:

  2. Customize an activity with bookmark:
    In the opening MyReadLineActivity.cs file, fill the 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 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.cs file 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.

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

By this statement, WF context creates a bookmark with arguments BookMarkName and BookMarkCallback. When wfApp.ResumeBookmark method is called, 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; default value is false.

In the following code snippet of step 3:

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

When this statement is executed, OnResumeBookmark method defined in MyReadLine activity will be called and the method will accept 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 store, run, and transmit workflow as 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 Chapter01 solution and name the project ConvertWFInstanceToXML. Delete the Workflow1.xaml file that is created by default.
  2. Write code to create 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 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 common XAML tasks of reading XAML and writing an object graph, or reading an object and writing out 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 using.

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 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 shown in the following screenshot:

  3. Create code to load up workflow instance from 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);
    }
    }
    }

    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()));

Summary

Having worked with our first WF program, in the next article we will cover testing and debugging a WF program.


Further resources on this subject:


About the Author :


Andrew Zhu

Andrew Zhu is a technology support engineer at Microsoft (Microsoft Globe Tech Support Center) in Shanghai. Over the past few years, he has helped developers and his customers to develop WF, BizTalk, IIS, and ASP.NET applications.

Books From Packt


WCF 4.0 Multi-tier Services Development with LINQ to Entities
WCF 4.0 Multi-tier Services Development with LINQ to Entities

Applied Architecture Patterns on the Microsoft Platform
Applied Architecture Patterns on the Microsoft Platform

NHibernate 3.0 Cookbook
NHibernate 3.0 Cookbook

Refactoring with Microsoft Visual Studio 2010
Refactoring with Microsoft Visual Studio 2010

Microsoft Enterprise Library 5.0
Microsoft Enterprise Library 5.0

Microsoft Dynamics AX 2009 Administration
Microsoft Dynamics AX 2009 Administration

Microsoft Azure: Enterprise Application Development
Microsoft Azure: Enterprise Application Development

Microsoft Windows Communication Foundation 4.0 Cookbook for Developing SOA Applications
Microsoft Windows Communication Foundation 4.0 Cookbook for Developing SOA Applications


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
j
s
C
j
F
E
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software