<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://community.bartdesmet.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>B# .NET Blog : Windows Workflow Foundation (WF)</title><link>http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx</link><description>Tags: Windows Workflow Foundation (WF)</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20423.869)</generator><item><title>Workflow - Talking about Local Communication Services synchronization</title><link>http://community.bartdesmet.net/blogs/bart/archive/2007/02/25/workflow-talking-about-local-communication-services-synchronization.aspx</link><pubDate>Sun, 25 Feb 2007 08:26:22 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:12208</guid><dc:creator>bart</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=12208</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2007/02/25/workflow-talking-about-local-communication-services-synchronization.aspx#comments</comments><description>&lt;p&gt;A question of one of my blog readers: what about multiple workflows calling into the same Local Communication Service concerning possible threading and synchronization issues.&lt;/p&gt; &lt;p&gt;Consider the following scenario. Assume you have one WorkflowRuntime in your host application, together with one registered Local Communication Service defined by the following interface contract:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:4b33f859-7633-4104-960f-186f2cce1b93" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="width:100%;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    [ExternalDataExchange]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;interface&lt;/span&gt;&lt;span style="color:#000000;"&gt; IBar
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Bar(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; i);
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Foo(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; i);
    }&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Assume Workflow1 relies on the Bar method while Workflow2 relies on the Foo method, with both workflow definitions like the following:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.bartdesmet.net/images/WorkflowTalkingaboutLocalCommunicationSe_10AF7/image06.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="459" src="http://www.bartdesmet.net/images/WorkflowTalkingaboutLocalCommunicationSe_10AF7/image0_thumb4.png" width="163" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The whileActivity1 has a condition that evaluatues true at all times (read: endless loop). The sequenceActivity1 acts as the container for a set of activities in the body of the loop, and wraps the callExternalMethodActivity1 (that calls the Bar and Foo method for Workflow1 and Workflow2 respectively) as well as the delayActivity1 (that has a 1 second and a 3 second delay for Workflow1 and Workflow2 respectively).&lt;/p&gt;
&lt;p&gt;Next, assume the following host application code (&lt;u&gt;note:&lt;/u&gt; there's a little issue in the code below since I'm running more than one workflow and the waitHandle would be set upon completion of one of both, causing the app to terminate - since both workflows won't ever terminate due to the endless loop, this doesn't cause further problems in this particular demo):&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:1d5bf8e2-e50e-4323-8f1c-2a4b08569eec" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="width:100%;"&gt;&lt;div&gt;&lt;span style="color:#999999;"&gt; 1&lt;/span&gt; &lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Program
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 2&lt;/span&gt; &lt;span style="color:#000000;"&gt;    {
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 3&lt;/span&gt; &lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Main(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] args)
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 4&lt;/span&gt; &lt;span style="color:#000000;"&gt;        {
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 5&lt;/span&gt; &lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt;(WorkflowRuntime workflowRuntime &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; WorkflowRuntime())
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 6&lt;/span&gt; &lt;span style="color:#000000;"&gt;            {
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 7&lt;/span&gt; &lt;span style="color:#000000;"&gt;                AutoResetEvent waitHandle &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; AutoResetEvent(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;false&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 8&lt;/span&gt; &lt;span style="color:#000000;"&gt;                workflowRuntime.WorkflowCompleted &lt;/span&gt;&lt;span style="color:#000000;"&gt;+=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;delegate&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
&lt;/span&gt;&lt;span style="color:#999999;"&gt; 9&lt;/span&gt; &lt;span style="color:#000000;"&gt;                workflowRuntime.WorkflowTerminated &lt;/span&gt;&lt;span style="color:#000000;"&gt;+=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;delegate&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; sender, WorkflowTerminatedEventArgs e)
&lt;/span&gt;&lt;span style="color:#999999;"&gt;10&lt;/span&gt; &lt;span style="color:#000000;"&gt;                {
&lt;/span&gt;&lt;span style="color:#999999;"&gt;11&lt;/span&gt; &lt;span style="color:#000000;"&gt;                    Console.WriteLine(e.Exception.Message);
&lt;/span&gt;&lt;span style="color:#999999;"&gt;12&lt;/span&gt; &lt;span style="color:#000000;"&gt;                    waitHandle.Set();
&lt;/span&gt;&lt;span style="color:#999999;"&gt;13&lt;/span&gt; &lt;span style="color:#000000;"&gt;                };
&lt;/span&gt;&lt;span style="color:#999999;"&gt;14&lt;/span&gt; &lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#999999;"&gt;15&lt;/span&gt; &lt;span style="color:#000000;"&gt;                ExternalDataExchangeService edx &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; ExternalDataExchangeService();
&lt;/span&gt;&lt;span style="color:#999999;"&gt;16&lt;/span&gt; &lt;span style="color:#000000;"&gt;                workflowRuntime.AddService(edx);
&lt;/span&gt;&lt;span style="color:#999999;"&gt;17&lt;/span&gt; &lt;span style="color:#000000;"&gt;                edx.AddService(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; MyService());
&lt;/span&gt;&lt;span style="color:#999999;"&gt;18&lt;/span&gt; &lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#999999;"&gt;19&lt;/span&gt; &lt;span style="color:#000000;"&gt;                WorkflowInstance instance1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; workflowRuntime.CreateWorkflow(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color:#000000;"&gt;(TestConcurrency.Workflow1));
&lt;/span&gt;&lt;span style="color:#999999;"&gt;20&lt;/span&gt; &lt;span style="color:#000000;"&gt;                instance1.Start();
&lt;/span&gt;&lt;span style="color:#999999;"&gt;21&lt;/span&gt; &lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#999999;"&gt;22&lt;/span&gt; &lt;span style="color:#000000;"&gt;                WorkflowInstance instance2 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; workflowRuntime.CreateWorkflow(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color:#000000;"&gt;(TestConcurrency.Workflow2));
&lt;/span&gt;&lt;span style="color:#999999;"&gt;23&lt;/span&gt; &lt;span style="color:#000000;"&gt;                instance2.Start();
&lt;/span&gt;&lt;span style="color:#999999;"&gt;24&lt;/span&gt; &lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#999999;"&gt;25&lt;/span&gt; &lt;span style="color:#000000;"&gt;                waitHandle.WaitOne();
&lt;/span&gt;&lt;span style="color:#999999;"&gt;26&lt;/span&gt; &lt;span style="color:#000000;"&gt;            }
&lt;/span&gt;&lt;span style="color:#999999;"&gt;27&lt;/span&gt; &lt;span style="color:#000000;"&gt;        }
&lt;/span&gt;&lt;span style="color:#999999;"&gt;28&lt;/span&gt; &lt;span style="color:#000000;"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;where MyService implements the IBar interface:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:7821a5bf-0cf3-4e45-b822-daa22ef49619" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="width:100%;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; MyService : IBar
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Bar(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; n)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; i &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; i &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;100&lt;/span&gt;&lt;span style="color:#000000;"&gt;; i&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                Thread.Sleep(&lt;/span&gt;&lt;span style="color:#800080;"&gt;10&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
                Console.Write(&lt;/span&gt;&lt;span style="color:#800000;"&gt;'&lt;/span&gt;&lt;span style="color:#800000;"&gt;#&lt;/span&gt;&lt;span style="color:#800000;"&gt;'&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
            }
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Foo(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; n)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; i &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; i &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;100&lt;/span&gt;&lt;span style="color:#000000;"&gt;; i&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                Thread.Sleep(&lt;/span&gt;&lt;span style="color:#800080;"&gt;10&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
                Console.Write(&lt;/span&gt;&lt;span style="color:#800000;"&gt;'&lt;/span&gt;&lt;span style="color:#800000;"&gt;@&lt;/span&gt;&lt;span style="color:#800000;"&gt;'&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
            }
        }
    }&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Question: Predict the console output of the workflow execution above. Tip: what about adding [MethodImpl(MethodImplOptions.Synchronized)] to the method declarations? What about inspecting the ManagedThreadId property of the Thread.CurrentThread in both methods?&lt;/p&gt;
&lt;p&gt;Happy threading!&lt;/p&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=12208" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category></item><item><title>WF - Hello World via the Command Line (wfc.exe explained)</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/12/07/WF-_2D00_-Hello-World-via-the-Command-Line.aspx</link><pubDate>Thu, 07 Dec 2006 22:08:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:12029</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=12029</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/12/07/WF-_2D00_-Hello-World-via-the-Command-Line.aspx#comments</comments><description>&lt;h1&gt;&lt;strong&gt;&lt;font color="#000080"&gt;Introduction&lt;/font&gt;&lt;/strong&gt;&lt;/h1&gt;&lt;p&gt;A reader of mine noticed I&amp;#39;m using Visual Studio 2005 as the tool to create all of my Windows Workflow Foundation related samples, instead of taking my favorite minimal command-line approach to create basic samples. So here it is today: a simple Hello World demo of WF using the command-line.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h1&gt;&lt;font color="#000080"&gt;Please welcome WFC&lt;/font&gt;&lt;/h1&gt;&lt;p&gt;Just like csc.exe is the C#&amp;#39;s programmer best friend, wfc.exe plays that role for WF programmers. Basically it turns a .xoml file (which stands for eXtensible Object Markup Language) into a .dll assembly file representing the workflow you&amp;#39;ve designed. Below you can see a simple demo.xoml file:&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;lt;&lt;font color="#800000"&gt;SequentialWorkflowActivity&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Name&lt;/font&gt;=&amp;quot;Demo&amp;quot; &lt;font color="#ff0000"&gt;x:Class&lt;/font&gt;=&amp;quot;FooBar.Demo&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;font color="#ff0000"&gt;xmlns:x&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;xmlns&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/workflow&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/winfx/2006/xaml/workflow&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;CodeActivity&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Name&lt;/font&gt;=&amp;quot;sayHello&amp;quot; &lt;font color="#ff0000"&gt;ExecuteCode&lt;/font&gt;=&amp;quot;sayHello_ExecuteCode&amp;quot;&lt;font face="courier new"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;x:Code&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;![CDATA[&lt;br /&gt;&lt;font color="#808080"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void sayHello_ExecuteCode(object sender, EventArgs e) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Hello World&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]]&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;x:Code&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;CodeActivity&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;lt;/&lt;font color="#800000"&gt;SequentialWorkflowActivity&lt;/font&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;This simple sample can be compiled into a .dll file by invoking the following:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;gt;wfc demo.xoml&lt;/font&gt;&lt;/p&gt;&lt;p&gt;In this case, we&amp;#39;ve been using a CDATA section to put the code inline between the XOML definition. Another approach would be to put the following in the demo.xoml file:&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;lt;&lt;font color="#800000"&gt;SequentialWorkflowActivity&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Name&lt;/font&gt;=&amp;quot;Demo&amp;quot; &lt;font color="#ff0000"&gt;x:Class&lt;/font&gt;=&amp;quot;FooBar.Demo&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;font color="#ff0000"&gt;xmlns:x&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;xmlns&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/workflow&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/winfx/2006/xaml/workflow&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;CodeActivity&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Name&lt;/font&gt;=&amp;quot;sayHello&amp;quot; &lt;font color="#ff0000"&gt;ExecuteCode&lt;/font&gt;=&amp;quot;sayHello_ExecuteCode&amp;quot; /&lt;font face="courier new"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&amp;lt;/&lt;font color="#800000"&gt;SequentialWorkflowActivity&lt;/font&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;and to create another file called demo.cs:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;System; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;namespace&lt;/font&gt; FooBar&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;partial class &lt;/font&gt;Demo&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;void&lt;/font&gt; sayHello_ExecuteCode(&lt;font color="#0000ff"&gt;object&lt;/font&gt; sender, &lt;font color="#008080"&gt;EventArgs&lt;/font&gt; e) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;Console&lt;/font&gt;.WriteLine(&lt;font color="#800000"&gt;&amp;quot;Hello World&amp;quot;&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt; &lt;/p&gt;&lt;p&gt;which can be compiled using:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;gt;wfc demo.xoml demo.cs&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Notice the use of the partial keyword in the class definition. In the end, the .xoml file is a partial definition of the workflow class, so the .cs file is another part of it and has to be marked as &amp;quot;partial&amp;quot;. Both compilations will yield the same assembly:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.bartdesmet.net/images/WFHelloWorldviatheCommandLine_140A3/image02.png"&gt;&lt;img border="0" height="302" src="http://www.bartdesmet.net/images/WFHelloWorldviatheCommandLine_140A3/image0_thumb.png" style="border:0px;" width="885" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Using the assembly in a host application is another concern of course. Basically you just have to compile the following piece of code with a reference to the demo.dll file generated above:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System;&lt;br /&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System.Threading;&lt;br /&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System.Workflow.Runtime; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;namespace&amp;nbsp;&lt;/font&gt;&lt;/font&gt;FooBar&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;class &lt;/font&gt;&lt;/font&gt;Hello&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;public static void &lt;/font&gt;&lt;/font&gt;Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;(&lt;font color="#008080"&gt;WorkflowRuntime&lt;/font&gt; workflowRuntime = &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;/font&gt;&lt;font color="#008080"&gt;WorkflowRuntime&lt;/font&gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;AutoResetEvent&lt;/font&gt; waitHandle = &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;/font&gt;&lt;font color="#008080"&gt;AutoResetEvent&lt;/font&gt;(false); &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowCompleted += &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;delegate&lt;/font&gt;&lt;/font&gt;(&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;object &lt;/font&gt;&lt;/font&gt;sender, &lt;font color="#008080"&gt;WorkflowCompletedEventArgs&lt;/font&gt; e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.Set();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;WorkflowInstance&lt;/font&gt; instance = workflowRuntime.CreateWorkflow(&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;&lt;/font&gt;(FooBar.&lt;font color="#008080"&gt;Demo&lt;/font&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance.Start(); &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.WaitOne();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt; &lt;/p&gt;&lt;p&gt;which might be a little difficult to add the reference to the System.Workflow assemblies which reside in the GAC. A more convenient demo approach is to merge the host application and the code-behind for the workflow into one single .cs file, like this:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System;&lt;br /&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System.Threading;&lt;br /&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System.Workflow.Runtime; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;namespace&amp;nbsp;&lt;/font&gt;&lt;/font&gt;FooBar&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;class &lt;/font&gt;&lt;/font&gt;Hello&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;public static void &lt;/font&gt;&lt;/font&gt;Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;(&lt;font color="#008080"&gt;WorkflowRuntime&lt;/font&gt; workflowRuntime = &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;/font&gt;&lt;font color="#008080"&gt;WorkflowRuntime&lt;/font&gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;AutoResetEvent&lt;/font&gt; waitHandle = &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;/font&gt;&lt;font color="#008080"&gt;AutoResetEvent&lt;/font&gt;(false); &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowCompleted += &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;delegate&lt;/font&gt;&lt;/font&gt;(&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;object &lt;/font&gt;&lt;/font&gt;sender, &lt;font color="#008080"&gt;WorkflowCompletedEventArgs&lt;/font&gt; e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.Set();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;WorkflowInstance&lt;/font&gt; instance = workflowRuntime.CreateWorkflow(&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;&lt;/font&gt;(FooBar.&lt;font color="#008080"&gt;Demo&lt;/font&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance.Start(); &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.WaitOne();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;partial class &lt;/font&gt;Demo&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;void&lt;/font&gt; sayHello_ExecuteCode(&lt;font color="#0000ff"&gt;object&lt;/font&gt; sender, &lt;font color="#008080"&gt;EventArgs&lt;/font&gt; e) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;Console&lt;/font&gt;.WriteLine(&lt;font color="#800000"&gt;&amp;quot;Hello World&amp;quot;&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;font face="courier new"&gt;&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Now compile this file (demo.cs) together with the .xoml file, as follows:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;gt;wfc /target:exe /r:System.Xml.dll demo.xoml demo.cs&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h1&gt;&lt;font color="#000080"&gt;MsBuild style&lt;/font&gt;&lt;/h1&gt;&lt;p&gt;There&amp;#39;s of course another approach that leans more towards Visual Studio 2005 compilation, i.e. using MsBuild. Assuming you have a file called demo.xoml:&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;lt;&lt;font color="#800000"&gt;SequentialWorkflowActivity&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Name&lt;/font&gt;=&amp;quot;Demo&amp;quot; &lt;font color="#ff0000"&gt;x:Class&lt;/font&gt;=&amp;quot;FooBar.Demo&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;font color="#ff0000"&gt;xmlns:x&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;xmlns&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/workflow&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/winfx/2006/xaml/workflow&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;CodeActivity&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Name&lt;/font&gt;=&amp;quot;sayHello&amp;quot; &lt;font color="#ff0000"&gt;ExecuteCode&lt;/font&gt;=&amp;quot;sayHello_ExecuteCode&amp;quot;&lt;font face="courier new"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;x:Code&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;![CDATA[&lt;br /&gt;&lt;font color="#808080"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void sayHello_ExecuteCode(object sender, EventArgs e) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;quot;Hello World&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]]&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;x:Code&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;CodeActivity&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;lt;/&lt;font color="#800000"&gt;SequentialWorkflowActivity&lt;/font&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;and a file called hello.cs:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System;&lt;br /&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System.Threading;&lt;br /&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;System.Workflow.Runtime; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;namespace&amp;nbsp;&lt;/font&gt;&lt;/font&gt;FooBar&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;class &lt;/font&gt;&lt;/font&gt;Hello&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;public static void &lt;/font&gt;&lt;/font&gt;Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;&lt;/font&gt;(&lt;font color="#008080"&gt;WorkflowRuntime&lt;/font&gt; workflowRuntime = &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;/font&gt;&lt;font color="#008080"&gt;WorkflowRuntime&lt;/font&gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;AutoResetEvent&lt;/font&gt; waitHandle = &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;/font&gt;&lt;font color="#008080"&gt;AutoResetEvent&lt;/font&gt;(false); &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowCompleted += &lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;delegate&lt;/font&gt;&lt;/font&gt;(&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;object &lt;/font&gt;&lt;/font&gt;sender, &lt;font color="#008080"&gt;WorkflowCompletedEventArgs&lt;/font&gt; e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.Set();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;WorkflowInstance&lt;/font&gt; instance = workflowRuntime.CreateWorkflow(&lt;font face="courier new"&gt;&lt;font color="#0000ff"&gt;typeof&lt;/font&gt;&lt;/font&gt;(FooBar.&lt;font color="#008080"&gt;Demo&lt;/font&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance.Start(); &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.WaitOne();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;you can create a .csproj build file that contains this:&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;lt;&lt;font color="#800000"&gt;Project&lt;/font&gt; &lt;font color="#ff0000"&gt;DefaultTargets&lt;/font&gt;=&amp;quot;Build&amp;quot; &lt;font color="#ff0000"&gt;xmlns&lt;/font&gt;=&amp;quot;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;"&gt;&lt;font color="#0000ff" face="courier new"&gt;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff" face="courier new"&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;PropertyGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;RootNamespace&lt;/font&gt;&amp;gt;&lt;font color="#000000"&gt;FooBar&lt;/font&gt;&amp;lt;/&lt;font color="#800000"&gt;RootNamespace&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;AssemblyName&lt;/font&gt;&amp;gt;&lt;font color="#000000"&gt;Demo&lt;/font&gt;&amp;lt;/&lt;font color="#800000"&gt;AssemblyName&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;OutputPath&lt;/font&gt;&amp;gt;&lt;font color="#000000"&gt;.&lt;/font&gt;&amp;lt;/&lt;font color="#800000"&gt;OutputPath&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;PropertyGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;ItemGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Reference&lt;/font&gt; &lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;System&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Reference&lt;/font&gt; &lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;System.Xml&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Reference &lt;/font&gt;&lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;System.Workflow.Activities&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Reference&lt;/font&gt; &lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;System.Workflow.ComponentModel&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Reference&lt;/font&gt; &lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;System.Workflow.Runtime&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;ItemGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;ItemGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Compile&lt;/font&gt; &lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;Hello.cs&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;DependentUpon&lt;/font&gt;&amp;gt;&lt;font color="#000000"&gt;demo.xoml&lt;/font&gt;&amp;lt;/&lt;font color="#800000"&gt;DependentUpon&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;SubType&lt;/font&gt;&amp;gt;&lt;font color="#000000"&gt;Component&lt;/font&gt;&amp;lt;/&lt;font color="#800000"&gt;SubType&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;Compile&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;ItemGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;ItemGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Content&lt;/font&gt; &lt;font color="#ff0000"&gt;Include&lt;/font&gt;=&amp;quot;demo.xoml&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;ItemGroup&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Import&lt;/font&gt; &lt;font color="#ff0000"&gt;Project&lt;/font&gt;=&amp;quot;$(MSBuildBinPath)\Microsoft.CSharp.Targets&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Import&lt;/font&gt; &lt;font color="#ff0000"&gt;Project&lt;/font&gt;=&amp;quot;$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/&lt;font color="#800000"&gt;Project&lt;/font&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;which can be built using:&lt;/p&gt;&lt;p&gt;&amp;gt;msbuild&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.bartdesmet.net/images/WFHelloWorldviatheCommandLine_140A3/image05.png"&gt;&lt;img border="0" height="448" src="http://www.bartdesmet.net/images/WFHelloWorldviatheCommandLine_140A3/image0_thumb1.png" style="border:0px;" width="677" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Enjoy command-line compiling WF-apps (for demo purposes only I hope)!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http://community.bartdesmet.net/blogs/bart/archive/2006/12/07/WF-_2D00_-Hello-World-via-the-Command-Line.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" border="0" height="30" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://community.bartdesmet.net/blogs/bart/archive/2006/12/07/WF-_2D00_-Hello-World-via-the-Command-Line.aspx" width="164" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=12029" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Working with events and the ListenActivity</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/10/19/4588.aspx</link><pubDate>Thu, 19 Oct 2006 09:09:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4588</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4588</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/10/19/4588.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This post builds upon the foundation created in &lt;A HREF="/blogs/bart/archive/2006/10/18/4587.aspx"&gt;yesterday's post&lt;/A&gt; about the &lt;STRONG&gt;HandleExternalEventActivity&lt;/STRONG&gt;. Please follow the instructions in that post before continuing with this one. As you've learned from this previous post, waiting for an external event to occur is a very powerful mechanism to drive execution of a workflow. There are a lot of scenarios however where you'll want to wait for more than one event at the same time, or you want to timeout such a wait for an event to get raised. To make this kind of dreams reality, WF has the &lt;STRONG&gt;ListenActivity&lt;/STRONG&gt; in its magic toolbox.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;The demo&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Take the solution you built in the &lt;A HREF="/blogs/bart/archive/2006/10/18/4587.aspx"&gt;previous post on working with events&lt;/A&gt;&amp;nbsp;and go to Workflow1.cs's designer view. It should look like this: &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/eventsdemo02.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Your next job is to transform this into the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/eventsdemobis01.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;An easy way to accomplish this is outlined below:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Add a &lt;STRONG&gt;ListenActivity&lt;/STRONG&gt; below the WhileActivity.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Rename the left branch of the ListenActivity to &lt;EM&gt;clientArrived&lt;/EM&gt; and the right branch to &lt;EM&gt;timeoutOccurred&lt;/EM&gt;.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Drag and drop the &lt;EM&gt;clientArrival&lt;/EM&gt; and &lt;EM&gt;doWork&lt;/EM&gt; activities from the while loop to the &lt;STRONG&gt;left branch&lt;/STRONG&gt;.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Delete the SequenceActivity from the WhileActivity's body.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Drag and drop the ListenActivity to the body of our WhileActivity.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Add a DelayActivity (set to 10 seconds) called &lt;EM&gt;timeout&lt;/EM&gt; to the &lt;STRONG&gt;right branch&lt;/STRONG&gt;, as well as a CodeActivity called &lt;EM&gt;oops&lt;/EM&gt; with the following ExecuteCode handler code:&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Cyan;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Oops! Timeout occurred"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ResetColor();&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;Basically, the ListenActivity blocks till one branch completes. Notice you can add additional branches, e.g. to listen to three, four, ... events at the same time:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/eventsdemobis02.jpg"&gt;&lt;/P&gt;
&lt;P&gt;When you try to execute this workflow, you'll see timeouts occurring when the client waits to long to enter&amp;nbsp;her name:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/eventsdemobis03.jpg"&gt;&lt;/P&gt;
&lt;P&gt;I'm sorry for the defaced console output, but hey that's not the goal of the demo is it?&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Waiting for one event to occur is a common requirement; waiting for multiple events can be even a more common requirement. WF makes it really easy to do this, without having to mess around with threading and waithandles (even more: in a stateful long-running world relying on additional runtime services like &lt;A HREF="/blogs/bart/archive/2006/10/14/4580.aspx"&gt;persistence&lt;/A&gt;) using the ListenActivity. I bet you'll find yourself leveraging the power of this activity on a regular basis, especially in combination with a DelayActivity to model timeouts. Now you know everything about waiting for events in WF, it's time to wake up yourself and don't wait any longer to explore WF! Cheers!&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4588" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Handling external events with HandleExternalEvent, External Data Exchange and Local Communications Services</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/10/18/4587.aspx</link><pubDate>Wed, 18 Oct 2006 08:04:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4587</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4587</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/10/18/4587.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In &lt;/FONT&gt;&lt;A HREF="/blogs/bart/archive/2006/10/17/4584.aspx"&gt;&lt;FONT face=Arial size=2&gt;yesterday's post&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt;, you learned that the vast majority of workflows need to exchange data with other parties to get their jobs done. Just one of the benefits of workflows is the possibility to visualize this kind of interaction by means of different activities, like the &lt;STRONG&gt;CallExternalMethodActivity&lt;/STRONG&gt; that was explained in the previous post. Based on a contract definition (read: interface) a workflow can be defined while the choice of the service implementation is left as a decision for the workflow host application. In today's post, we continue our journey on the Local Communication Services and External Data Exchange path with the &lt;STRONG&gt;HandleExternalEventActivity&lt;/STRONG&gt;.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Scenario&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The &lt;STRONG&gt;CallExternalMethodActivity&lt;/STRONG&gt; explained in the &lt;A HREF="/blogs/bart/archive/2006/10/17/4584.aspx"&gt;previous post&lt;/A&gt; is used to perform methods calls from inside the workflow to some service. Based on an interface and method contract, the workflow can be defined. At runtime, an appropriate service implementation is attached to the workflow and chosen by the engine to process service requests. An example is a workflow calling to an order processing system in some way defined by the contract (e.g. PlaceOrder).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Beside making calls from the workflow to some party outside, one can also rely on the host application to notify the workflow when it needs to do something. This is done using the &lt;STRONG&gt;HandleExternalEventActivity&lt;/STRONG&gt; which makes a workflow block till the corresponding event (again in a contract-based manner) is raised by some service. As an example, think of a workflow waiting for approval based on some event (e.g. OrderApproved).&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;A simple demo&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;Workflow definition&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;As usual on this blog, we'll try to keep things simple and approachable, to focus on the basics of the topic discussed. Create a simple Sequential Workflow Console application called EventsDemo:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/eventsdemo01.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Next, create the following workflow definition in Workflow1.cs:&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/eventsdemo02.jpg"&gt;&lt;/P&gt;
&lt;P&gt;This needs some elaboration. On top, we have some CodeActivity called start with the simple ExecuteCode event handler displayed below. At the bottom, there's a similar activity with the event handler shown below as well:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; start_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Green;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Waiting for clients..."&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.ResetColor();&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; stop_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Red;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Served 5 clients; time for early retirement!"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;.ResetColor();&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Next, there's an activity called &lt;EM&gt;clientListener&lt;/EM&gt; of the type &lt;STRONG&gt;WhileActivity&lt;/STRONG&gt;. This one just loops till five clients have been served, based on the following Declarative Rule Condition:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;this.clientCount &amp;lt; 5&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;relying on the following private variable in the code-behind:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; clientCount = 0;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;A WhileActivity can only contain one single child activity. Because of this, a SequenceActivity is added to the body of the WhileActivity. Inside this SequenceActivity, two child activities are added:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;EM&gt;clientArrival&lt;/EM&gt; is of type HandleExternalEventActivity and will be discussed below shortly&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;doWork&lt;/EM&gt; is of type CodeActivity and has the following ExecuteCode event handler:&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; doWork_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Yellow;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Event captured - Hello {0}. You're client number {1}."&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;, args.Name, clientCount);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.ResetColor();&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT size=2&gt;The core of the workflow is the &lt;STRONG&gt;HandleExternalEventActivity&lt;/STRONG&gt; called &lt;EM&gt;clientArrival&lt;/EM&gt;. This activity works in a similar way as the CallExternalMethodActivity and relies on an interface and in this case an event to wait for. The logical next step is to define this interface (IBar.cs):&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; System;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; System.Workflow.Activities;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;namespace&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; EventsDemo&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; [&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ExternalDataExchange&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;interface&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;IBar&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; event&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt; Foo;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; [&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Serializable&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; : &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;ExternalDataEventArgs&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; FooEventArgs(&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Guid&lt;/FONT&gt;&lt;FONT size=2&gt; instanceId, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; name) : &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;base&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;(instanceId)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.name = name;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; name;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; Name&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; name; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { name = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;Notice the interface definition being annotated with the &lt;STRONG&gt;ExternalDataExchangeAttribute&lt;/STRONG&gt;, which is required for workflow to communicate with it using Local Communication Services. Next, the defined event has an event arguments object derived from &lt;STRONG&gt;ExternalDataEventArgs&lt;/STRONG&gt;. The constructor of this event arguments object is worth to mention because it requires a base call to one of the base class's constructors that require a workflow instance identifier to be passed on:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; FooEventArgs(&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Guid&lt;/FONT&gt;&lt;FONT size=2&gt; instanceId, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; name) : &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;base&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(instanceId)&lt;BR&gt;{&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;This is required for the workflow runtime to be able to correlate the event with the right workflow instance.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;When you've defined the interface with the event, you can continue to set up the HandleExternalEvent activity. Start by setting the InterfaceType to the IBar interface. Next, set the EventName to Foo. In order to capture the event arguments in the workflow instance to d something useful with it in a later stage, you can bind the &lt;EM&gt;e&lt;/EM&gt; parameter (à la EventArgs e) to some local variable:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; args;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; Args&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; args; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { args = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;Finally hook up an event handler for the Invoked event of the HandleExternalEvent activity. This will be used to increment the counter that keeps track of the number of served clients (you could do this inside the &lt;EM&gt;doWork&lt;/EM&gt; CodeActivity too):&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; clientArrival_Invoked(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ExternalDataEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; clientCount++;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;Notice you could use this event handler too in order to extract information from the event args that were raised with the exception.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Finally, the property grid of the HandleExternalEventActivity &lt;EM&gt;clientArrival&lt;/EM&gt; should look like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;img src="http://www.bartdesmet.net/images/eventsdemo03.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;STRONG&gt;The host&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;On to the host side now&lt;/FONT&gt;&lt;FONT size=2&gt;. What we want to do, is ask the end-user for a name and then raise the event to the workflow&amp;nbsp;instance to indicate a "client arrival". The workflow should then proceed in the WhileActivity loop and perform work for the newly arrived user.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;To do this, we'll first &lt;STRONG&gt;implement IBar&lt;/STRONG&gt; as follows:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Bar&lt;/FONT&gt;&lt;FONT size=2&gt; : &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;IBar&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;event&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt; Foo;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; RaiseEvent(&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Guid&lt;/FONT&gt;&lt;FONT size=2&gt; instanceId, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; name)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (Foo != &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt; evt = Foo;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FooEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; args = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;FooEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;(instanceId, name);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; evt(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;, args);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;Next, to establish the communication between the workflow and the "Bar" service, we need to register an ExternalDataExchangeService (from System.Workflow.Activities):&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;bar = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Bar&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ExternalDataExchangeService&lt;/FONT&gt;&lt;FONT size=2&gt; svc = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ExternalDataExchangeService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;();&lt;BR&gt;workflowRuntime.AddService(svc);&lt;BR&gt;svc.AddService(bar);&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;I've created &lt;EM&gt;bar&lt;/EM&gt; as a local variable in the host class:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Bar&lt;/FONT&gt;&lt;FONT size=2&gt; bar;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;Once the workflow instance is started, we'll start a new thread (rather quick-n-dirty) to accept user input till the workflow terminates:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008080 size=2&gt;WorkflowInstance&lt;/FONT&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(EventsDemo.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Workflow1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;));&lt;BR&gt;instance.Start();&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Thread&lt;/FONT&gt;&lt;FONT size=2&gt; userInput = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Thread&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;(UserInput);&lt;BR&gt;userInput.Start(instance.InstanceId);&lt;BR&gt;&lt;BR&gt;waitHandle.WaitOne();&lt;BR&gt;&lt;BR&gt;userInput.Abort();&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;That is, the background thread &lt;EM&gt;userInput&lt;/EM&gt; is started with a parameter to indicate the workflow instance to raise events in. When the workflow completes (when &lt;EM&gt;waitHandle&lt;/EM&gt; is set), the background thread is aborted (there exist cleaner ways to implement this idea, but for demo purposes this should be okay). &lt;/FONT&gt;&lt;FONT size=2&gt;This background thread is defined as follows:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;static&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; UserInput(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; instanceId)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; (; ; )&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Thread&lt;/FONT&gt;&lt;FONT size=2&gt;.Sleep(500); &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000 size=2&gt;//dirty demo trick&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.Write(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"User name: "&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string&lt;/FONT&gt;&lt;FONT size=2&gt; name = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.ReadLine();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;bar.RaiseEvent((&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&lt;STRONG&gt;&lt;U&gt;Guid&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;) instanceId, name);&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;The core line of code is indicated in bold and does the real work of notifying the workflow instance of the simulated "client arrival". Don't worry about the Thread.Sleep call which is just there to keep the console output nice and smooth in a very dirty way to keep things simple and clean.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Now run the application, it should produce the following output (enter a few names and see what happens):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;img src="http://www.bartdesmet.net/images/eventsdemo04.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Local communication between a workflow and external data services is an absolute must for a lot of workflow scenarios. In this post and the &lt;A HREF="/blogs/bart/archive/2006/10/17/4584.aspx"&gt;previous post&lt;/A&gt;, you learned how to establish this kind of communication with a workflow in both directions, by making method calls and by waiting for events to occur. Enjoy!&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4587" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Introducing External Data Exchange, the CallExternalMethodActivity and Local Communications Services</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/10/17/4584.aspx</link><pubDate>Tue, 17 Oct 2006 19:25:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4584</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4584</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/10/17/4584.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Workflows don't stand on their own; they need a host application to run in but in a lot of cases there's more: external services are needed to provide functionality to the workflow. You might think, let's just use&amp;nbsp;a CodeActivity to call into some piece of functionality but that doesn't offer enough flexibility in most cases. Okay, you can work with an interface and parameterize the workflow, but still the workflow doesn't reveal its intentions visibly: a CodeActivity is an opaque container where the visualized world of workflows is traded for procedural code again.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Enter the &lt;STRONG&gt;Communication Services&lt;/STRONG&gt;, part one. In this post, you'll learn how to exchange data with the workflow by hooking in a "external data exchange service".&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;CallExternalMethodActivity&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;At the core of external data exchange is the CallExternalMethodActivity. In a later post, we'll focus on HandleExternalEvent but for now, let's just rely on plain simple method calls. The scenario is the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;We need a workflow to get the job done (for reasons that may vary a lot, which have been discussed extensively already).&lt;/LI&gt;
&lt;LI&gt;It can't be 100% self-contained and has to rely on external services to process things, for example to make an order.&lt;/LI&gt;
&lt;LI&gt;This external service communication needs a big deal of genericity, so that it can be replaced by an alternative implementation when required. In other words, it needs to be &lt;STRONG&gt;contract-based&lt;/STRONG&gt;.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;EM&gt;(And no, it isn't a web service we want to call, because in that case we could rely on InvokeWebService.)&lt;/EM&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Demo&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;A workflow definition&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Right, on to the demo with a somewhat simplified contract: let's call a simple calculator to get things done (I don't want to get the curse of the bad demo gods :-)). Start by creating a simple console-based workflow application:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;img src="http://www.bartdesmet.net/images/externaldatademo01.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, add a single CallExternalMethodActivity from the toolbox to the workflow definition as shown below:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;img src="http://www.bartdesmet.net/images/externaldatademo02.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This is what you should get to see when you set the properties correctly as outlined below. First, go to the code behind of the workflow and add three properties:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; A&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { a = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; B&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { b = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; result;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; Result&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; result; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { result = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now, add an interface to the project called ICalculator:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT face="Courier New"&gt;[&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;&lt;STRONG&gt;&lt;U&gt;ExternalDataExchange&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;]&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;interface&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;ICalculator&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Add(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Subtract(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Multiply(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Divide(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; b);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Notice the use of the &lt;A href="http://windowssdk.msdn.microsoft.com/en-us/library/system.workflow.activities.externaldataexchangeattribute.aspx"&gt;ExternalDataExchangeAttribute&lt;/A&gt;, which lives in System.Workflow.Activities. This indicates the interface acts as the contract for external data exchange.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now go back to the designer and set the CallExternalMethodActivity properties. Start by specifying the InterfaceType:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;img src="http://www.bartdesmet.net/images/externaldatademo03.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, set the MethodName to Add. Then&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;, set the parameters a, b and (ReturnValue) that appear in the property grid to point to the properties A, B and Result respectively:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;img src="http://www.bartdesmet.net/images/externaldatademo04.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If you've done things correctly, this should result in the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;img src="http://www.bartdesmet.net/images/externaldatademo05.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Right, so now your workflow knows how to transform some input parameters into the corresponding output.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;Letting the host know about data services&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;That's all what's needed for the workflow definition itself. On to the &lt;STRONG&gt;host&lt;/STRONG&gt; now (Program.cs). First, we'll parameterize the workflow instantiation as follows:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;Dictionary&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;gt; parameters = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Dictionary&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt;&amp;gt;();&lt;BR&gt;parameters.Add(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"A"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt;, 1);&lt;BR&gt;parameters.Add(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"B"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;, 2);&lt;/U&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowInstance&lt;/FONT&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(ExternalDataDemo.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Workflow1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;), &lt;STRONG&gt;&lt;U&gt;parameters&lt;/U&gt;&lt;/STRONG&gt;);&lt;BR&gt;instance.Start();&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, create some class that implements ICalculator. In this case this is very straightforward since we live in the same project as the workflow definition. In reality you'd have to reference the assembly with the interface definition of course. For the sake of the demo, a simple implementation as a nested class inside Program will meet our needs:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;class&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CalculatorService&lt;/FONT&gt;&lt;FONT size=2&gt; : &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;ICalculator&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; #region&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; ICalculator Members&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Add(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a + b;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Subtract(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a - b;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Multiply(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a * b;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Divide(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; a / b;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp; #endregion&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now it's time to hook in this service to the workflow runtime, so that instances can rely on it to get their jobs done. This is done in the Program class again, as follows:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;ExternalDataExchangeService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; edx = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ExternalDataExchangeService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;();&lt;BR&gt;workflowRuntime.AddService(edx); &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008000 size=2&gt;//keep this order!&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;edx.AddService(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CalculatorService&lt;/FONT&gt;&lt;FONT size=2&gt;()); &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;//keep this order!&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;It's important to keep the order of the last two lines, otherwise you'll end up with an exception. Also, import the System.Workflow.Activities namespace that contains the &lt;A href="http://windowssdk.msdn.microsoft.com/en-us/library/system.workflow.activities.externaldataexchangeservice.aspx"&gt;ExternalDataExchangeService&lt;/A&gt; class. This class acts as a container for all external data exchange services, i.e. implementations of interfaces that were annotated with the ExternalDataExchangeAttribute earlier on. &lt;EM&gt;You can only have one implementation of each service.&lt;/EM&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Finally, to get the result back, we'll change the WorkflowCompleted event handler as displayed below:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; res = 0;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;AutoResetEvent&lt;/FONT&gt;&lt;FONT size=2&gt; waitHandle = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;AutoResetEvent&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;workflowRuntime.WorkflowCompleted += &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;delegate&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowCompletedEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;res = (&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt;) e.OutputParameters[&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Result"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;];&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp; waitHandle.Set();&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;...&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In here, &lt;EM&gt;res&lt;/EM&gt; is a variable declared on top of the the Main method which gets printed out at the end of the method:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;WorkflowInstance&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(ExternalDataDemo.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Workflow1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;), parameters);&lt;BR&gt;instance.Start();&lt;BR&gt;&lt;BR&gt;waitHandle.WaitOne();&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#008080 size=2&gt;Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(res);&lt;/P&gt;&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The result when executing should be obvious :-).&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Exchanging data with external parties should be apparent when looking at the workflow definition. Therefore, one has created the CallExternalMethodActivity to encapsulate such a call for external data. By doing so, external data exchange has the potential to become just yet another service, like &lt;A HREF="/blogs/bart/archive/2006/10/15/4582.aspx"&gt;tracking&lt;/A&gt; and &lt;A HREF="/blogs/bart/archive/2006/10/14/4580.aspx"&gt;persistence&lt;/A&gt;. In the next post, we'll talk about events. Enjoy!&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4584" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Using the WorkflowMonitor in combination with Dynamic Updates</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/10/16/4585.aspx</link><pubDate>Mon, 16 Oct 2006 20:15:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4585</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4585</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/10/16/4585.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In the past, I've been talking about making a workflow dynamic by applying changes to it at runtime:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;&lt;A HREF="/blogs/bart/archive/2006/08/28/4322.aspx"&gt;WF&amp;nbsp;- How to make a workflow dynamic? - Part 1&lt;/A&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;&lt;A HREF="/blogs/bart/archive/2006/08/31/4369.aspx"&gt;WF - How to make a workflow dynamic? - Part 2&lt;/A&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;A HREF="/blogs/bart/archive/2006/10/15/4582.aspx"&gt;Yesterday&lt;/A&gt;, you learned how to use tracking (and persistence) services to visualize what's going on inside a workflow in flight, using the WorkflowMonitor sample application that comes with the Windows SDK. Today, we'll combine both the dynamic adaptation of a workflow with tracking services.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Modifying the WorkflowMonitor&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;As discussed &lt;A HREF="/blogs/bart/archive/2006/10/15/4582.aspx"&gt;yesterday&lt;/A&gt;, the &lt;STRONG&gt;WorkflowMonitor&lt;/STRONG&gt; tracks workflows by polling a tracking database used by WF. To visualize what's a workflow keeping itself busy with, it relies on the workflow definition type that gets loaded in the &lt;STRONG&gt;workflow designer&lt;/STRONG&gt; that's rehosted by the sample application. However, when making dynamic changes, the WorkflowMonitor doesn't visualize the modifications made&amp;nbsp;to the workflow, because the type doesn't get &lt;STRONG&gt;reload&lt;/STRONG&gt;ed. To make things work in a quick-n-dirty fashion, you'll need to change the WorkflowMonitor sample a bit (one line to be precise).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Go to MainForm.cs and locate the method called &lt;STRONG&gt;UpdateActivities&lt;/STRONG&gt;. Change the code as follows (only a few lines are displayed, just enough for you to find the spot where modification is needed):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;...&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008080 size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;ListViewItem&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; currentWorkflow = listViewWorkflows.SelectedItems[0];&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (currentWorkflow != &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Guid&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; workflowInstanceId = workflowStatusList[(currentWorkflow.SubItems[0]).Text].InstanceId;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; SqlTrackingWorkflowInstance&lt;/FONT&gt;&lt;FONT size=2&gt; sqlTrackingWorkflowInstance = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt; == monitorDatabaseServiceValue.TryGetWorkflow(workflowInstanceId, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;out&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; sqlTrackingWorkflowInstance))&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;//Edited by Bart De Smet - 10/05/06&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;GetWorkflowDefinition(workflowInstanceId);&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;//End edit&lt;/U&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; listViewActivities.Items.Clear();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; activityStatusListValue.Clear();&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Dynamic updates&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;To keep things easy, I'll rely on the results of &lt;A HREF="/blogs/bart/archive/2006/10/15/4582.aspx"&gt;yesterday's work&lt;/A&gt;, so follow those instructions first and make sure the app runs fine. Then go to Workflow1.cs in the TrackingDemoLibrary project and change the ExecuteCode eventhandler for allowAccess like this:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; allowAccess_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Green;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"You're granted access"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.ResetColor();&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;WorkflowChanges&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt; wc = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowChanges&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;);&lt;BR&gt;&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;CodeActivity&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt; hello = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CodeActivity&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"hello"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;);&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;hello.ExecuteCode += &lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;&lt;U&gt;(hello_ExecuteCode);&lt;BR&gt;&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;IfElseActivity&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#000000 size=2&gt; ageChecker = (&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;IfElseActivity&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;)wc.TransientWorkflow.Activities[&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"ageChecker"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New" color=#000000&gt;&lt;STRONG&gt;&lt;U&gt;];&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;IfElseBranchActivity&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt; plusEighteen = (&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;IfElseBranchActivity&lt;/FONT&gt;&lt;FONT size=2&gt;)ageChecker.GetActivityByName(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"plusEighteen"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;);&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;plusEighteen.Activities.Add(hello);&lt;BR&gt;&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;this&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;U&gt;.ApplyWorkflowChanges(wc);&lt;/U&gt;&lt;/STRONG&gt;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Next, add another delay on top of the workflow, set to 10 seconds. This will give us the opportunity to see the dynamic change happen in the WorkflowMonitor:&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/dynmonitor03.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Recompile and &lt;STRONG&gt;&lt;FONT color=#ff0000&gt;make sure to re-register the workflow definition assembly in the GAC&lt;/FONT&gt;&lt;/STRONG&gt;:&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/dynmonitor02.jpg"&gt;&lt;/P&gt;
&lt;P&gt;You might need to recreate the tracking database too (that the easy way to clean it when doing demos), as explained in the &lt;A HREF="/blogs/bart/archive/2006/10/15/4582.aspx"&gt;post on Tracking Services&lt;/A&gt;. Just drop the SqlTrackingDatabase, create it again and execute the two .sql scripts.&lt;/P&gt;
&lt;P&gt;Now start the &lt;STRONG&gt;&lt;FONT color=#ff0000&gt;adapted (see above) WorkflowMonitor&lt;/FONT&gt;&lt;/STRONG&gt; and then start the TrackingDemo solution. Keep an eye on the WorkflowMonitor and see what happens:&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/dynmonitor04.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/dynmonitor05.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/dynmonitor06.jpg"&gt;&lt;/P&gt;
&lt;P&gt;The result of the execution looks as follows thanks to dynamic adaptation:&lt;/P&gt;
&lt;P&gt;&lt;img src="http://www.bartdesmet.net/images/dynmonitor01.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Tracking in a world of dynamic updates is even more interesting and with one simple change to the WorkflowMonitor sample code, one creates a very appealing piece of tracking functionality. Have fun!&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4585" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Working with Tracking Services</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/10/15/4582.aspx</link><pubDate>Sun, 15 Oct 2006 10:15:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4582</guid><dc:creator>bart</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4582</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/10/15/4582.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In the &lt;/FONT&gt;&lt;A HREF="/blogs/bart/archive/2006/10/14/4580.aspx"&gt;&lt;FONT face=Arial size=2&gt;previous post&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt; I've covered the use of persistence services with Windows Workflow Foundation to enable long-running workflows in a reliable way. However, there's still another dark side to long-running workflows that needs a solution: what's happening inside? As you can imagine, a workflow in progress can be blocked waiting for a lot of things, such as the expiration of a timer to indicate a timeout (e.g. by putting a DelayActivity in parallel with another activity using a ParallelActivity) or a wait for an external chunk of data to arrive. In order to visualize what's going on inside, at runtime, the WF Gods created tracking services.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Getting started&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Just like persistence services, tracking services&amp;nbsp;rely on some store to put information - in casu tracking information - in. Again, WF comes with a SQL Server enabled service out of the box, called the &lt;A href="http://windowssdk.msdn.microsoft.com/en-us/library/ms665167.aspx"&gt;SqlTrackingService&lt;/A&gt;. There's quite a bit to tell about tracking services, but we'll stick with the basics in this post. Nevertheless, a short list of cool things:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Filtering tracking information using &lt;STRONG&gt;tracking profiles&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Querying tracked information using &lt;STRONG&gt;SqlTrackingQuery&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;These might get covered in much more detail somewhere in the future. As usual, in case you have questions, you can contact me too.&lt;/P&gt;
&lt;P&gt;Right, on the the real stuff now. To enable tracking services using SQL Server (2000, 2005, MSDE, Express) we need to create a tracking database first. We'll use SQL Server 2005 Express Edition in this post (&lt;A href="http://msdn.microsoft.com/vstudio/express/sql/download/"&gt;download here&lt;/A&gt;) with SQL Server Management Studio Express installed on the machine:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Connect to the database server:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo01.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Create a new database called SqlTrackingDemo:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo02.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Now define the database structure and logic required by tracking services, based on two .sql scripts that ship with WF in the %windir%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN folder:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo03.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Execute (in order) &lt;STRONG&gt;Tracking_Schema.sql&lt;/STRONG&gt; and &lt;STRONG&gt;Tracking_Logic.sql&lt;/STRONG&gt;, while making sure you've selected the newly created database from step 2:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo04.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Finally you should find a bunch of tables and stored procedures in the database (check this).&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;A tracking-enabled workflow project&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;A simple solution&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Create a new&amp;nbsp;Sequential Workflow Console Application first, called &lt;STRONG&gt;TrackingDemo&lt;/STRONG&gt;:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo05.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Remove Workflow1 from the Solution Explorer and add a new Sequential Workflow Library project to the solution, called &lt;STRONG&gt;TrackingDemoLibrary&lt;/STRONG&gt;:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo06.jpg"&gt;&lt;/P&gt;
&lt;P&gt;This step is required because we'll use our workflow definition to visualize tracking information and to do so, the assembly containing the workflow definition will be put in the GAC (as shown later on). Next, &lt;STRONG&gt;add a reference&lt;/STRONG&gt; to the TrackingDemoLibrary project in the TrackingDemo (host) project:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo07.jpg"&gt;&lt;/P&gt;
&lt;P&gt;In the code of the host application (Program.cs) change the call to CreateWorkflow as follows:&lt;/P&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;WorkflowInstance&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;U&gt;&lt;STRONG&gt;TrackingDemoLibrary.&lt;/STRONG&gt;&lt;/U&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&lt;U&gt;&lt;STRONG&gt;Workflow1&lt;/STRONG&gt;&lt;/U&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;));&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;Finally, go the &lt;STRONG&gt;project properties of TrackingDemoLibrary&lt;/STRONG&gt; and make the assembly strong-named:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo08.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Defining the workflow&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now go to Workflow1 in the TrackingDemoLibrary project. First, &lt;STRONG&gt;parameterize&lt;/STRONG&gt; the workflow by adding two&amp;nbsp;properties to the code:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; firstName;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; FirstName&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; firstName; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { firstName = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; age;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; Age&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; age; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { age = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Now create the following &lt;STRONG&gt;workflow definition&lt;/STRONG&gt;:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo09.jpg"&gt;&lt;/P&gt;
&lt;P&gt;In here, the IfElseActivity's plusEighteen branch relies on a &lt;STRONG&gt;Declarative Rule Condition&lt;/STRONG&gt; defined as follows:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo10.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo11.jpg"&gt;&lt;/P&gt;
&lt;P&gt;The ExecuteCode event handlers for the different CodeActivity activities are defined like this:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; welcome_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Welcome "&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; + firstName);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; allowAccess_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Green;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"You're granted access"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.ResetColor();&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; denyAccess_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Red;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"You're denied access"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;.ResetColor();&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Finally, the delay activities in the workflow were added to simulate long-running operations and have a timeout value set to 10 seconds.&lt;/P&gt;
&lt;P&gt;To test things, go to the Program.cs file and change the workflow instance creation code to pass through parameters:&lt;/P&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT face="Courier New"&gt;Dictionary&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;gt; parameters = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Dictionary&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;&amp;gt;();&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;U&gt;parameters.Add(&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#800000 size=2&gt;"FirstName"&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Bart"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;);&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;U&gt;parameters.Add(&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;&lt;STRONG&gt;&lt;U&gt;"Age"&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;, 23);&lt;BR&gt;&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowInstance&lt;/FONT&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(TrackingDemoLibrary.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Workflow1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;), &lt;STRONG&gt;&lt;U&gt;parameters&lt;/U&gt;&lt;/STRONG&gt;);&lt;BR&gt;instance.Start();&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;No magic yet:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo12.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Track it&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Time to enable tracking. This is done by adding just one single line of code to the host code (Program.cs):&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;using&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; System.Workflow.Runtime.Tracking;&lt;BR&gt;&lt;BR&gt;...&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;workflowRuntime.AddService(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;SqlTrackingService&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Data Source=localhost\\SQLEXPRESS;Initial Catalog=SqlTrackingDemo;Integrated Security=SSPI;"&lt;/FONT&gt;&lt;FONT size=2&gt;));&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;Now, execute the application once more and then go to the SQL Server Management Studio Express to execute the following query:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;use&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; SqlTrackingDemo&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT face="Courier New"&gt;exec&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT size=2&gt;GetWorkflows&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;This will result in something like this (a few columns were hidden in the screenshot):&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo13.jpg"&gt;&lt;/P&gt;
&lt;P&gt;In here you can see the identifier of the workflow instance as well as information about the workflow type. Other database tables include much more detailed information about the current state the workflow is in, effectively enabling tracking scenarios. Instead of doing low level work with these tables or stored procedures, we'll use a monitor application to see what's going on.&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Lights on the WorkflowMonitor&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;When you install the Windows SDK, a folder with samples is created on the system, typically in %programfiles%\Microsoft SDKs\Windows\v6.0\Samples:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo14.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Extract the WFSamples.zip folder to some location on your system. In the &lt;STRONG&gt;Applications\WorkflowMonitor\CS&lt;/STRONG&gt; subfolder of the samples, you'll find a WorkflowMonitor application that we'll take a look at now. Open it in Visual Studio 2005.&lt;/P&gt;
&lt;P&gt;Now run the application. After a few seconds, the app will crash with the following error message:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo15.jpg"&gt;&lt;/P&gt;
&lt;P&gt;This is because we didn't use the default configuration for tracking (i.e. different database name etc). However, we get the opportunity to change the settings right away:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo16.jpg"&gt;&lt;/P&gt;
&lt;P&gt;The settings shown above are the valid ones in our case, using SQL Server 2005 Express with the right database name and a polling time of 5 seconds.&lt;/P&gt;
&lt;P&gt;When you now try to start the monitoring (using the green "play" button) you'll likely see the following error (or something similar). You might need to restart the application to see the message popping up too:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo17.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Basically this means that the WorkflowMonitor is able to get the workflows using GetWorkflows but now tries to load the type specified in the database to visualize the workflows (which may be&amp;nbsp;in flight). For the WorkflowMonitor to find our &lt;STRONG&gt;TrackingDemoLibrary.Workflow1&lt;/STRONG&gt; type, it will need to find the assembly containing the definition. You can either copy the dll file to the bin\Debug (or bin\Release depending on how you're running the WorkflowMonitor sample) folder of the WorkflowMonitor or register the workflow definition in the GAC. We choose the latter one:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo18.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Now restart the WorkflowMonitor and you should see something like this:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo19.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Notice the mark signs indicate the followed path during execution. It's a very interesting time investment to look at the code of this sample to find out how the workflow information is queried using &lt;STRONG&gt;SqlTrackingQuery&lt;/STRONG&gt;. This sample is also interesting because of the &lt;STRONG&gt;designer rehosting&lt;/STRONG&gt; used to visualize the workflow in the right-hand side pane. I'll cover designer rehosting some time in the future on this blog too.&lt;/P&gt;
&lt;P&gt;Now, run our workflow application again while the monitor is polling the tracking database. Contrary to what you might expect, you won't see a new workflow instance appearing in the list right away. This happens because tracking only performs its job when asked so, e.g. because of a persistence opportunity (this statement is somewhat simplified, check out the docs to get full info on how the system works, related to work batches and so on). As an exercise, try to combine persistence (see &lt;A HREF="/blogs/bart/archive/2006/10/14/4580.aspx"&gt;previous post&lt;/A&gt;) with tracking to track a workflow in progress. You'll end up with a piece of hosting code like this:&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;workflowRuntime.AddService(&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;SqlWorkflowPersistenceService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Data Source=localhost\\SQLEXPRESS;Initial Catalog=SqlPersistenceDemo;Integrated Security=SSPI;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TimeSpan&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.FromHours(1.0),&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; TimeSpan&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.FromSeconds(5.0)&lt;BR&gt;&amp;nbsp;&amp;nbsp; )&lt;BR&gt;);&lt;BR&gt;&lt;BR&gt;workflowRuntime.AddService(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;SqlTrackingService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Data Source=localhost\\SQLEXPRESS;Initial Catalog=SqlTrackingDemo;Integrated Security=SSPI;"&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp; )&lt;BR&gt;);&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Chances are high your app will block or throw an exception. This is because the system needs to connect to the two databases at the same time in a transactional manner. To have this work, you need to start the &lt;STRONG&gt;DTC service&lt;/STRONG&gt; on your machine:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo20.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Now execute the app again and you should see the following in the monitor:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/trackingdemo21.jpg"&gt;&lt;/P&gt;
&lt;P&gt;As you can see, it's now possible to &lt;STRONG&gt;&lt;FONT color=#ff0000&gt;monitor a workflow in flight&lt;/FONT&gt;&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Note:&lt;/U&gt;&lt;/STRONG&gt; An alternative approach to avoid the DTC problem is to use the - fasten your seatbelts - &lt;A href="http://windowssdk.msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.sharedconnectionworkflowcommitworkbatchservice.aspx"&gt;SharedConnectionWorkflowCommitBatchService&lt;/A&gt; service instead of a combination of the tracking service and the persistence service. As the name implies, this one uses a shared connection for both, effectively avoiding distributed transactions and the need for DTC to be enabled and started on the machine. I won't cover this here.&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The use of long-running workflows in combination with a lot of services can turn the whole thing in a opaque box without you (and managers) knowing what's going on inside. Tracking services are the window into the internals of workflow instances in all their states, even when in progress. Combining this goodness with things like designer rehosting can open up a lot of great scenarios as shown in the WorkflowMonitor sample.&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4582" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Working with Persistence Services</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/10/14/4580.aspx</link><pubDate>Sun, 15 Oct 2006 03:48:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4580</guid><dc:creator>bart</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4580</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/10/14/4580.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In the past, I've been &lt;/FONT&gt;&lt;A HREF="/blogs/bart/archive/category/1004.aspx"&gt;&lt;FONT face=Arial size=2&gt;writing about WF&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt; quite a bit. If you haven't read these articles already, you might find it interesting to check these out first before digging into this one. That being said, this post will focus on &lt;STRONG&gt;persistence services&lt;/STRONG&gt; (also known as &lt;EM&gt;state persistence services&lt;/EM&gt;).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Why persistence?&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Before we dive deeper in the technical details, let's answer a crucial question: why persistence? As you probably know by now, workflows can be defined (at least partially) as a great tool to visualize either human workflow (e.g. approval processes) or machine workflow (e.g. business integration scenarios). Instead of writing procedural code, one creates a flow diagram or state diagram that represents the underlying logic that gets managed by the workflow runtime and engine. Read my &lt;A HREF="/blogs/bart/archive/2006/08/27/4278.aspx"&gt;WF introduction post&lt;/A&gt; for more information on this.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;A common question is why one would prefer to use workflow instead of classic procedural code. There are a lot of answers to the question, one of which relates to the &lt;STRONG&gt;graphical&lt;/STRONG&gt; aspect of a workflow that makes it more approachable and easier to understand. Another good answer is the support for scenarios that would end up with a rather high level &lt;STRONG&gt;complexity&lt;/STRONG&gt; in procedural code, like parallel execution, data exchange with other components, transactional support, etc. Yet another one - the one that will interest us most - is a set of &lt;STRONG&gt;runtime services&lt;/STRONG&gt; available to cope with more complex situations, including persistence services.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Beside the distinction of state workflows and sequential workflows and the distinction between machine workflows and human workflows, one can also draw a line between &lt;STRONG&gt;long-running&lt;/STRONG&gt; and non-long-running workflows. It's not atypical (even more, rather typical) for workflows to be long-running. For example, approval processes will require human interaction by one or more parties to continue the workflow execution. Yet another example is a business integration application that waits for external data to arrive. In such a case we say a workflow to be &lt;STRONG&gt;idled&lt;/STRONG&gt;. Needless to say, it would be a waste of resources (and even unreliable) to keep state of an idle workflow in memory. That's why we need persistence services.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;The basics: getting idle&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;We'll start by taking a look at a workflow becoming idle. Start by creating a simple sequential workflow:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo01.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;To force a workflow getting idle, we can use the DelayActivity. So, define the following workflow, containing a DelayActivity with the delay set to 10 seconds:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo02.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo03.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, define the ExecuteCode event handler for both CodeActivity activities as follows:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; codeActivity1_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Green;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"CodeActivity1 speaking"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.ResetColor();&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; codeActivity2_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.ForegroundColor = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ConsoleColor&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.Green;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"CodeActivity2 speaking"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;.ResetColor();&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;When you launch this workflow application, no surprises will happen. At least not visibly (yet). The workflow will be launched, the "CodeActivity1 speaking" message will be printed out, the workflow will pause for 10 seconds, and then "CodeActivity2 speaking" will appear. Behind the scenes however, the workflow is idled when the delay activity is started. To visualize this, go to the host application's Program.cs file and hook in an event handler for the WorkflowIdled event as show below:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;Program&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Main(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;[] args)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowRuntime&lt;/FONT&gt;&lt;FONT size=2&gt; workflowRuntime = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowRuntime&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;())&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoResetEvent&lt;/FONT&gt;&lt;FONT size=2&gt; waitHandle = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;AutoResetEvent&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowCompleted += &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;delegate&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowCompletedEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e) {waitHandle.Set();};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowTerminated += &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;delegate&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowTerminatedEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.WriteLine(e.Exception.Message);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.Set();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&lt;STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;U&gt;workflowRuntime.WorkflowIdled += &lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;&amp;gt;(workflowRuntime_WorkflowIdled);&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WorkflowInstance&lt;/FONT&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(PersistenceDemo.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Workflow1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance.Start();&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.WaitOne();&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; workflowRuntime_WorkflowIdled(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008080 size=2&gt;Console&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Idled "&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt; + e.WorkflowInstance.InstanceId);&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;STRONG&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/STRONG&gt;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Run the application now. It should print the following before it completes (i.e. screenshot taken during the delay activity execution):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo04.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;How persistence works&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;When a workflow gets idle, it can be persisted, so that it can be unloaded from memory. A persistence service inherits from the &lt;A href="http://windowssdk.msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowpersistenceservice.aspx"&gt;System.Workflow.Hosting.WorkflowPersistenceService&lt;/A&gt; base class that's used by the workflow engine to perform persistence. I recommend you to check out this class. Workflow comes with a SQL Server driven persistence service out of the box, defined in &lt;A href="http://windowssdk.msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.sqlworkflowpersistenceservice.aspx"&gt;System.Workflow.Hosting.SqlWorkflowPersistenceService&lt;/A&gt;.&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;When a workflow gets idle, the system checks in the registered services to find a persistence service, if any. If it finds when, the persistence service gets called to perform the persistence. Next, the system uses the persistence information to find out about the "next timer expiration" to wake up the idled workflow instance when required, so that it can continue its job executing.&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Setting up persistence&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The first step to set up persistence using SQL Server (2000, MSDE, 2005, Express) is to create the persistence database. In this post, I'll use &lt;STRONG&gt;SQL Server 2005 Express Edition&lt;/STRONG&gt; to illustrate the persistence service. You can download the software &lt;A href="http://msdn.microsoft.com/vstudio/express/sql/download/"&gt;over here&lt;/A&gt;. Don't forget to install &lt;STRONG&gt;SQL Server Management Studio Express&lt;/STRONG&gt; too.&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Open SQL Server Management Studio Express and connect to the server (typically localhost\SQLEXPRESS):&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo05.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Next, create a new database called SqlPersistenceDemo, either by invoking CREATE DATABASE or by using the tools:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo06.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Now it's time to define the database by executing the WF .sql scripts provided in %windir%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo07.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;First, execute &lt;STRONG&gt;SqlPersistenceService_Schema.sql&lt;/STRONG&gt;, then execute &lt;STRONG&gt;SqlPersistenceService_Logic.sql&lt;/STRONG&gt;. Make sure to use the right database when you execute the scripts (SqlPersistenceDemo):&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo08.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;You're ready. The persistence database should contain the following tables and sprocs:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo09.jpg"&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Now, we can alter the code to support persistence. This is done in&amp;nbsp;the host application by creating an instance of the SqlWorkflowPersistence class and registering it as a service with the workflow runtime:&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;workflowRuntime.AddService(&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;SqlWorkflowPersistenceService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Initial Catalog=SqlPersistenceDemo;Data Source=localhost\\SQLEXPRESS;Integrated Security=SSPI;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TimeSpan&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.FromHours(1.0),&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TimeSpan&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;.FromSeconds(5.0)&lt;BR&gt;&amp;nbsp;&amp;nbsp; )&lt;BR&gt;);&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;The first parameter is straightforward and points to the database. In this case I'm using the SQLEXPRESS instance and connecting using windows integrated authentication. The second parameter is called "unloadOnIdle" which unloads the workflow when it's idled. This is the point in time where persistence happens. The third parameter isn't relevant for our elaboration right now and is used when multiple hosts can hydrate/dehydrate workflow instances from the database (it sets the ownership duration for the host, so that if another host tries to load the instance during that interval, it doesn't succeed in doing so and an exception will be thrown). The last parameter specifies the loading interval used to check whether a workflow instance has to be dehydrated (i.e. loaded from the database). We set this value to 5 seconds for the sake of the demo.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tip:&lt;/STRONG&gt; Check out SqlConnectionStringBuilder is you didn't do so yet and you want a more structured approach to create a connection string:&lt;/P&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;SqlConnectionStringBuilder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; sb = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;SqlConnectionStringBuilder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;();&lt;BR&gt;sb.IntegratedSecurity = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;;&lt;BR&gt;sb.DataSource = &lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"localhost\\SQLEXPRESS"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;;&lt;BR&gt;sb.InitialCatalog = &lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"SqlPersistenceDemo"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; connString = sb.ToString();&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Testing it&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Time to test. But before we do so, let's hook in another set of event handlers to find out about unload/load/persist events for the workflow:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;workflowRuntime.WorkflowIdled += &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;gt;(workflowRuntime_WorkflowIdled);&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowLoaded += &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt;(workflowRuntime_WorkflowLoaded);&lt;BR&gt;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowUnloaded += &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt;(workflowRuntime_WorkflowUnloaded);&lt;BR&gt;&amp;nbsp;&amp;nbsp; workflowRuntime.WorkflowPersisted += &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventHandler&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt;(workflowRuntime_WorkflowPersisted);&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;...&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; workflowRuntime_WorkflowPersisted(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Persisted {0} on {1}"&lt;/FONT&gt;&lt;FONT size=2&gt;, e.WorkflowInstance.InstanceId, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT size=2&gt;.Now.ToUniversalTime());&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; workflowRuntime_WorkflowUnloaded(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Unloaded {0} on {1}"&lt;/FONT&gt;&lt;FONT size=2&gt;, e.WorkflowInstance.InstanceId, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT size=2&gt;.Now.ToUniversalTime());&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; workflowRuntime_WorkflowLoaded(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Loaded {0} on {1}"&lt;/FONT&gt;&lt;FONT size=2&gt;, e.WorkflowInstance.InstanceId, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT size=2&gt;.Now.ToUniversalTime());&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; workflowRuntime_WorkflowIdled(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Idled {0} on {1}"&lt;/FONT&gt;&lt;FONT size=2&gt;, e.WorkflowInstance.InstanceId, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT size=2&gt;.Now.ToUniversalTime());&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;
&lt;P&gt;Before we press the magic F5 button, there's one more thing to do. Go to &lt;STRONG&gt;SQL Server Management Studio Express&lt;/STRONG&gt; and create a new query:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;use&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; SqlPersistenceDemo&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;RetrieveAllInstanceDescriptions&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT size=2&gt;InstanceState&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;Basically, the two are almost identical. Generally, I'd recommend to rely on the stored procedures to retrieve information about the workflow instances in progress, but let's just illustrate both:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo10.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Now, run the workflow application. You'll see something like this:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo11.jpg"&gt;&lt;/P&gt;
&lt;P&gt;As you can see, the idled event is followed by unloading the workflow, thanks to the persistence service (cf. the second "unloadOnIdle" parameter in the constructor call of SqlPersistenceService). Next, when the workflow is unloaded, it's time to persist the workflow instance in the database. While the application is running you have 10 seconds to re-run the query to see this:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo13.jpg"&gt;&lt;/P&gt;
&lt;P&gt;If you want to understand how a workflow is persisted, check out the Windows SDK documentation on writing a custom persistence service (search for "&lt;SPAN id=nsrTitle&gt;Creating Custom Persistence Services&lt;/SPAN&gt;"). All of this works using serialization of the runtime workflow instance state.&lt;/P&gt;
&lt;P&gt;Finally, the workflow will be reloaded and execution continues:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/persistencedemo12.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Notice execution didn't proceed after 10 seconds, but it took 15 seconds instead. The reason for this is the specified loading interval (cf. last parameter to the SqlPersistenceService constructor parameter). Based on this interval, the runtime checks whether a timer has expired amongst the persisted workflow instances.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tip:&lt;/STRONG&gt; Lower the delay's TimeoutDuration to 9 seconds and see what happens. Keep in mind little delays incurred by the runtime to do the persistence when&amp;nbsp;analyzing the results.&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In this post, we've seen the basics of the workflow state persistence services. Thanks to this service, long-running workflows can be implemented efficiently without you having to worry much about the persistence itself. In other words, services like persistence services free developers from the burden to cope with error-prone tasks and recurring patterns like implementing persistence. In the next workflow post, I'll focus on the tracking service, so keep an eye on my RSS feed.&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4580" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Exposing a workflow via WCF</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/09/04/4392.aspx</link><pubDate>Mon, 04 Sep 2006 22:34:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4392</guid><dc:creator>bart</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4392</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/09/04/4392.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In my &lt;A HREF="/blogs/bart/archive/2006/09/03/4388.aspx"&gt;previous post&lt;/A&gt; on Windows Workflow Foundation I covered how to expose a workflow via .NET 2.0 web services. You saw how easy it is to do this thanks to the built-in support in the Visual Studio 2005 Extension for Workflow. However, the next-generation service platform is Windows Communication Foundation (WCF), and so we'll take a look into the basics of hosting a workflow in WCF.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Defining a workflow&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;We'll start this demo by creating a new Empty Workflow Project, as shown below. The reason to choose a workflow project is to have the VS2005 Extension for Workflow loaded, which we wouldn't have if another non-WF project type is chosen.&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf01.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, add a new Sequential Workflow to the project (State Machine Workflows will be covered in a later post) and call it Adder. Needless to say the use of WF (and the calculator service around it) is useless for this kind of applications, but hey that's what demos are all about isn't it? We'll just examing how to host a workflow inside a WCF host, dot.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008000&gt;&lt;U&gt;Tip:&lt;/U&gt; Choose the &lt;EM&gt;Sequential Workflow (with code separation)&lt;/EM&gt; item. You can compare this with code-behind separation in ASP.NET. One file will contain markup (in this case that will be the .xoml file - XOML stands for eXtensible Object Markup Language) and another one (the code-behind file if you want) contains the C# code you'll be adding (.xoml.cs extension).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf02.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;On the workflow, add one single CodeActivity called &lt;EM&gt;add&lt;/EM&gt;. Next, create an event handler for ExecuteCode with the following piece of code in it:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; add_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; result = a + b;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In here a, b and result are private members that have a corresponding (starting with upper-case) property as shown below (prop-prop-prop):&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; A&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { a = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; B&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { b = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; result;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; Result&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; result; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { result = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf03.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Adding the WCF service&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The next step is to add a WinFX Service (in later builds this will likely be changed to reflect the .NET Framework 3.0 branding), which we'll call CalculatorService.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf04.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In the CalculatorService.cs file you'll find an interface called ICalculatorService and a class called CalculatorService implementing that interface. The interface is called the &lt;STRONG&gt;service contract&lt;/STRONG&gt; and has to changed as follows:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;[&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;ServiceContract&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;()]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;interface&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;ICalculatorService&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; [&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;OperationContract&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Add(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; [&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;OperationContract&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Subtract(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; [&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;OperationContract&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Multiply(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; [&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;OperationContract&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;]&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;FONT size=2&gt; Divide(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; b);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;We'll only be implementing the Add method, you can create an implementation for the other methods yourself if you want. &lt;FONT color=#008000&gt;&lt;U&gt;Tip:&lt;/U&gt; Divide is somewhat more tricky because you have to cope with a "division by zero" situation. To solve that problem, go and find out about FaultContracts in WCF and play around&amp;nbsp;a bit.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, change the CalculatorService class as outlined below. &lt;FONT color=#006400&gt;&lt;U&gt;Tip:&lt;/U&gt; Put the cursor somewhere in the ICalculator part of the class declaration, click on the smart tag and choose to implement the interface (implicitly) - or press SHIFT-ALT-F10. &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;Leave the Subtract, Multiply and Divide methods as they are now, i.e. just throwing an exception (&lt;EM&gt;&lt;FONT color=#800080&gt;I still wonder why the VS 2005 IDE folks didn't choose the NotImplementedException for this piece of auto code generation; &lt;A href="http://blogs.msdn.com/ansonh/archive/2005/12/08/501763.aspx"&gt;or not?&lt;/A&gt;&lt;/FONT&gt;&lt;/EM&gt;):&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Subtract(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; throw&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Exception&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"The method or operation is not implemented."&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Multiply(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; throw&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Exception&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"The method or operation is not implemented."&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Divide(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; throw&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Exception&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"The method or operation is not implemented."&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The Add method is the most interesting one of course:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; Add(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt; a, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; res = 0;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp; using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowRuntime&lt;/FONT&gt;&lt;FONT size=2&gt; wr = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowRuntime&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;())&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoResetEvent&lt;/FONT&gt;&lt;FONT size=2&gt; waitHandle = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;AutoResetEvent&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wr.WorkflowCompleted +=&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkflowCompletedEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; res = (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt;)e.OutputParameters[&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Result"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;];&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.Set();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dictionary&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;gt; arguments = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Dictionary&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; arguments.Add(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"A"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;, a);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; arguments.Add(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"B"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;, b);&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WorkflowInstance&lt;/FONT&gt;&lt;FONT size=2&gt; wi = wr.CreateWorkflow(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Adder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;), arguments);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wi.Start();&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waitHandle.WaitOne();&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; res;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This should be familiar from &lt;A HREF="/blogs/bart/archive/category/1004.aspx"&gt;previous posts&lt;/A&gt;. One thing that might be new is the use of &lt;STRONG&gt;output parameters&lt;/STRONG&gt;:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;res = (&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT size=2&gt;)e.OutputParameters[&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Result"&lt;/FONT&gt;&lt;FONT size=2&gt;];&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;It might be a little hard to read the code from top to bottom because the result is grabbed from the anonymous method that's hooked in to the WorkflowCompleted event.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In order to make our service functional, we have to create a &lt;STRONG&gt;configuration file&lt;/STRONG&gt; first:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf07.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;As you should have seen already, the CalculatorService.cs file contains a comment section on how to create the configuration file. Uncomment the configuration XML and cut-paste it into the &amp;lt;configuration&amp;gt; section of the app.config file. Next, make some changes (indicated in bold and underlined - &lt;STRONG&gt;&lt;U&gt;&lt;FONT face="Courier New"&gt;3 changes&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt; in total):&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;lt;?&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#800000 size=2&gt;xml&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;1.0&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;encoding&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;utf-8&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt; ?&amp;gt;&lt;BR&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;configuration&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;system.serviceModel&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;services&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; Before deployment, you should remove the returnFaults behavior configuration to avoid disclosing information in exception messages &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;--&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;service&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;STRONG&gt;&lt;U&gt;name&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;WFviaWCF.CalculatorService&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;behaviorConfiguration&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;returnFaults&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;endpoint&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;contract&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;WFviaWCF.ICalculatorService&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;binding&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;wsHttpBinding&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;&lt;U&gt;&amp;lt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT color=#800000 size=2&gt;endpoint&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;contract&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;IMetadataExchange&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;binding&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;mexHttpBinding&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;address&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;mex&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;STRONG&gt;&lt;U&gt; /&amp;gt;&lt;BR&gt;&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;service&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;services&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;behaviors&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;serviceBehaviors&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;behavior&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;returnFaults&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt; &amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;U&gt;&lt;STRONG&gt;&amp;lt;&lt;/STRONG&gt;&lt;/U&gt;&lt;/FONT&gt;&lt;U&gt;&lt;STRONG&gt;&lt;FONT color=#800000 size=2&gt;serviceMetadata&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;httpGetEnabled&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/U&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;U&gt;&lt;STRONG&gt; /&amp;gt;&lt;BR&gt;&lt;/STRONG&gt;&lt;/U&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;serviceDebug&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;includeExceptionDetailInFaults&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt; /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;behavior&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;serviceBehaviors&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;behaviors&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;system.serviceModel&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;configuration&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000000&gt;The first change is required because of a configuration schema change (the service's &lt;EM&gt;type&lt;/EM&gt; attribute has changed to become a &lt;EM&gt;name&lt;/EM&gt; attribute); the other two changes enable MEX (Metadata EXchange) that allows us to create a web service proxy (read: retrieve the WSDL service definition over HTTP).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;A console application host&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next on our to-do list is the creation of a hosting application. You could choose for a Windows Service or walk the path of IIS hosting (slightly more difficult ways) but we'll stick with a simple console application. So add a new class file to the project and call it Program.cs:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf05.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Change the code of the Program.cs file like this:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; System;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;namespace&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; WFviaWCF&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;Program&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyServiceHost&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;.StartService();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;.ReadLine();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This code uses the MyServiceHost class that was auto-generated as part of the WinFX Service creation process (see CalculatorService.cs for its definition) and just starts the service and waits for user input to stop the service host.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Before we can launch the application we'll need to set the project properties to compile to a console application with a given entry point:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf06.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Running the application&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Time to press F5 and see the Console application service host in action. Whoops, something goes wrong (assuming you're running on Vista and you haven't elevated yourself to run VS2005 with administrator privileges). No worries, I wouldn't post this if I hadn't a solution in mind...&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf08.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;What happens is this: Windows Vista has a kernel-mode listener called &lt;A href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/a2a45c42-38bc-464c-a097-d7a202092a54.mspx?mfr=true"&gt;http.sys&lt;/A&gt; (just like Windows Server 2003 and Windows XP SP2). All HTTP traffic passes through it. But before an app can start listening on an HTTP address, it needs to get registered with http.sys. More specifically the user account running the service host needs to have permission to use a URL to start listening on. In Windows Server 2003 and Windows XP SP2 there's a tool called &lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp"&gt;httpcfg.exe&lt;/A&gt;&lt;/STRONG&gt; (see &lt;A href="http://technet2.microsoft.com/WindowsServer/en/library/e17527d2-105a-451f-8e3f-d515479527011033.mspx?mfr=true"&gt;TechNet&lt;/A&gt;; see &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=49AE8576-9BB9-4126-9761-BA8011FABF38&amp;amp;displaylang=en"&gt;Support Tools for Windows XP&lt;/A&gt;). However it &lt;FONT color=#ff0000&gt;doesn't ship with Windows Vista&lt;/FONT&gt;. &lt;FONT color=#008000&gt;Geeks could compile httpcfg.exe from the code comes with&amp;nbsp;the Platform SDK (folder Samples\NetDS\HTTP\ServiceConfig).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;However, the god news is that &lt;STRONG&gt;httpcfg.exe is dead&lt;/STRONG&gt;. It's successor is called &lt;STRONG&gt;netsh http&lt;/STRONG&gt;. So, go to a command prompt, elevated using "Run as administrator", and do the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf09.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The command used in here is&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT face="Courier New"&gt;add urlacl url=http://+:8080/WFviaWCF/CalculatorService user=VISTA-9400\Bart&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;and contains the &lt;EM&gt;url&lt;/EM&gt; as displayed in our AddressAccessDeniedException, plus the &lt;EM&gt;user&lt;/EM&gt; who is allowed to use the URL (replace it by your DOMAIN\user). Alternatively you can also allow access to the URL to BUILTIN\Users or \Everyone but please understand the possible security risks when doing so.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Try to launch the application again, it should work correctly now. Time to open up a browser and go to &lt;A href="http://localhost:8080/WFviaWCF/CalculatorService"&gt;http://localhost:8080/WFviaWCF/CalculatorService&lt;/A&gt;. It should look like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf10.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If it looks like the screenshot below, you've not configured MEX correctly as I outlined earlier on. Notice however that WCF helps you out with the problem so you don't need to know the XML configuration syntax by head.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf11.jpg"&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;A client application&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In order to test our service we'll have to build a client application now. Just open another instance of Visual Studio 2005 and create a new console application called WFviaWCFClient. Next, go to the solution explorer, right-click and choose &lt;STRONG&gt;Add Service Reference&lt;/STRONG&gt;. &lt;FONT color=#008000&gt;This the WCF-equivalent of Add Web Reference and calls &lt;STRONG&gt;svcutil.exe&lt;/STRONG&gt; behind the scenes (instead of wsdl.exe). It fully supports WCF channels and the contract methodology but you can inspect this yourself if you like in the Service References\localhost.map\localhost.cs file that will get generated.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf12.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Enter the Service URI and accept the default Service reference name. Finally click on OK:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf13.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Last but not least, change the main method in program.cs like this:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Main(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;[] args)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a = 1, b = 2;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; localhost.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CalculatorServiceClient&lt;/FONT&gt;&lt;FONT size=2&gt; svc = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; localhost.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CalculatorServiceClient&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"{0} + {1} = {2}"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;, a, b, svc.Add(a, b));&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;.ReadLine();&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Time to run the application (almost ashame to show you such a trivial calculation, so that explains the little image below :-)):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfwcf14.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008000&gt;&lt;U&gt;Exercise:&lt;/U&gt; Make multiple calls to the Add method and notice you don't end up with an exception like we did in the &lt;/FONT&gt;&lt;A HREF="/blogs/bart/archive/2006/09/03/4388.aspx"&gt;&lt;FONT color=#008000&gt;ASP.NET 2.0 Web Service scenario&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#008000&gt;. Why is this? (&lt;U&gt;Tip:&lt;/U&gt; think about persistence, sessions and our WCF host implementation).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Hosting our workflow behind a service facade using WCF shouldn't be difficult at all (&lt;FONT color=#008000&gt;try to experiment with other transport mechanisms, check out the WCF documentation&lt;/FONT&gt;). However, keep in mind this was a trivial stateless example. Also notice the lack (today) of&amp;nbsp;equivalents to the WebServiceInput/Output/Fault activities. More complex scenarios (supporting state etc) will require more work; I'll come back to this later on, so keep an eye on my blog.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;See you again in the WF space soon!&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4392" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item><item><title>WF - Exposing a workflow through a web service</title><link>http://community.bartdesmet.net/blogs/bart/archive/2006/09/03/4388.aspx</link><pubDate>Sun, 03 Sep 2006 17:06:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:4388</guid><dc:creator>bart</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=4388</wfw:commentRss><comments>http://community.bartdesmet.net/blogs/bart/archive/2006/09/03/4388.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Introduction&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Previously in my &lt;A HREF="/blogs/bart/archive/category/1004.aspx"&gt;WF blog series&lt;/A&gt; I've been talking about the WF basics as well as dynamic updates to workflow instances at runtime. These posts had one thing in common: all of the demo applications were hosted in a simple console application, that was for the lion's part generated by the Visual Studio 2005 WF Extension. As you probably know by now, WF is about an &lt;STRONG&gt;in-process workflow engine&lt;/STRONG&gt; where hosting the WF runtime is required to get it to work. In this post, you'll see how to host WF in ASP.NET 2.0 and expose it through a web service.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;A simple workflow library&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000&gt;&lt;STRONG&gt;Creating the project&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;In the previous posts, we started coding by creating a Workflow-enabled console application. This time however, we need to create a library that defines a workflow. Later on, this workflow definition will be used by a web service in an ASP.NET website. So, open Visual Studio 2005 and create a new Sequential Workflow Library project entitled "WorkflowViaWS":&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws01.jpg"&gt;&lt;/P&gt;
&lt;P&gt;In order to concentrate on the real topic of this post, i.e. web service hosting of workflows, we'll create a trivial workflow: a &lt;STRONG&gt;divider&lt;/STRONG&gt;. So, rename Workflow1.cs to Divider.cs first.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;A webservice 'contract'&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now, when talking about web services one word should pop up in your brain almost instantaneously: the contract. Although we're not yet working with WCF over here, WF also has kind of a contract notion. Basically, we need to create an interface that will act as the interface to the workflow and hence the workflow that encapsulates our workflow. Add a new &lt;STRONG&gt;interface&lt;/STRONG&gt; to the project called IDivider:&lt;/P&gt;&lt;FONT color=#0000ff&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;namespace&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; WorkflowViaWS&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;interface&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080&gt;IDivider&lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;double&lt;/FONT&gt; Divide(&lt;FONT color=#0000ff&gt;double&lt;/FONT&gt; a, &lt;FONT color=#0000ff&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt; b);&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Accepting input == WebServiceInputActivity&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now we're ready to define the workflow itself. In order to accept input from the web service, we need to use a &lt;STRONG&gt;WebServiceInputActivity&lt;/STRONG&gt; from the Toolbox.&lt;/P&gt;
&lt;P&gt;When you drag and drop this activity to the workflow's designer surface, the designer will tell you to set the &lt;STRONG&gt;IsActivating&lt;/STRONG&gt; property of the activity to true. This is required to tell the system that this web service input actually activates the (new) workflow instance. &lt;FONT color=#008000&gt;Think about this for a while ... you can indeed have more than one WebServiceInputActivity in your workflow: welcome to the world of stateful webservices and state hydration/dehydration. This falls outside the scope of this post however, but stay tuned to discover this too!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Next, the designer will ask you to set the &lt;STRONG&gt;InterfaceType&lt;/STRONG&gt; property. This is where IDivider enters the scene. Setting the property couldn't be a simpler job thanks to the dialog support:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws02.jpg"&gt;&lt;/P&gt;
&lt;P&gt;Next you'll have to set the &lt;STRONG&gt;MethodName&lt;/STRONG&gt; with the assistance of a dropdown list in the Properties pane. Needless to say we'll choose the only method available: Divide.&lt;/P&gt;
&lt;P&gt;Now pay attention to the Properties pane: a set of &lt;STRONG&gt;Parameter&lt;/STRONG&gt; fields will come out of the blue:&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws03.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Setting these fields is quite easy again, but there's some work to do first: &lt;STRONG&gt;adding properties&lt;/STRONG&gt; to the Divider workflow class:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; A&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; a; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { a = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; B&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; b; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { b = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;U&gt;Tip:&lt;/U&gt; use the prop code snippet in Visual Studio 2005 as shown below (type 'prop' without quotes and press TAB).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws04.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;These properties will act as inputs to the workflow, just like we did in the previous posts with our console-hosted workflows and the arguments dictionary passed to CreateWorkflow. This is how the properties &lt;U&gt;would be&lt;/U&gt; used in a console-based application (or another non-WS hosting environment):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;FONT color=#008080&gt;Dictionary&lt;/FONT&gt;&amp;lt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;, &lt;FONT color=#0000ff&gt;object&lt;/FONT&gt;&amp;gt; arguments = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;Dictionary&lt;/FONT&gt;&amp;lt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;, &lt;FONT color=#0000ff&gt;object&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;gt;();&lt;BR&gt;arguments.Add(&lt;FONT color=#800000&gt;"A"&lt;/FONT&gt;, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;10.0);&lt;BR&gt;arguments.Add(&lt;FONT color=#800000&gt;"B"&lt;/FONT&gt;,&amp;nbsp; &lt;FONT face="Courier New" size=2&gt;2.0);&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008080&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=2&gt;WorkflowInstance&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; instance = workflowRuntime.CreateWorkflow(&lt;FONT color=#0000ff&gt;typeof&lt;/FONT&gt;(WorkflowViaWS.&lt;FONT color=#008080&gt;Divider&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;), arguments);&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Binding a parameter to a property is assisted by the following dialog that shows all of the valid candidates for binding. Bind parameter 'a' to property 'A' and parameter 'b' to property 'B':&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws05.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now we have completed all the required properties of the WebServiceInputActivity, the system still complains about something else...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;What goes in must go out - WebServiceOutputActivity&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;A web service hosted workflow won't do much if it couldn't produce results (&lt;FONT color=#008000&gt;so, there's no built-in concept of "one-way web methods"&amp;nbsp;available, although you can think of workarounds for that&lt;/FONT&gt;). &lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws06.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Therefore, add a &lt;STRONG&gt;WebServiceOutputActivity&lt;/STRONG&gt; activity to the designer (of course below the&amp;nbsp;WebServiceInputActivity)&amp;nbsp;and set its &lt;STRONG&gt;InputActivityName&lt;/STRONG&gt; to &lt;EM&gt;webServiceInput1&lt;/EM&gt;, the name of the corresponding input activity (note: I've been lazy with the acitivy naming in here, but since we only have one input and one output activity this doesn't matter much - btw, you're absolutely right to discard this excuse).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Next, we have to set the &lt;STRONG&gt;(ReturnValue)&lt;/STRONG&gt; property of the output activity. Again, we'll add a property to the workflow class:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; result;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; Result&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; result; }&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { result = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Selecting the return value is done using exactly the same dialog as we used to set the input parameter bindings. The result should look like:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws07.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;Division by zero? Fault! - Some additional logic&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In Kindergarten (or a bit later) everyone learned that dividing by zero isn't possible. The .NET Framework however takes a more mathematical approach and the result of dividing some double value by zero will be &lt;STRONG&gt;NAN&lt;/STRONG&gt; (not-a-number). Let's take the former approach which gives us the opportunity to add some additional logic to the workflow and illustrate the &lt;STRONG&gt;WebServiceFaultActivity&lt;/STRONG&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Perform the following jobs:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Drag and drop an &lt;STRONG&gt;IfElseActivity&lt;/STRONG&gt; to the designer surface in between the input and output activities. Rename it to &lt;EM&gt;divisionByZeroCheck&lt;/EM&gt;.&lt;/LI&gt;
&lt;LI&gt;As you can see the IfElseActivity has two branches. Select the left branch and rename it to &lt;EM&gt;isZero&lt;/EM&gt;. Then select the right branch and rename it to &lt;EM&gt;nonZero&lt;/EM&gt;.&lt;/LI&gt;
&lt;LI&gt;The&amp;nbsp;designer now complains on the left (&lt;EM&gt;isZero&lt;/EM&gt;) branch and asks&amp;nbsp;to set the &lt;STRONG&gt;Condition&lt;/STRONG&gt; property.&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;In the Properties pane, select &lt;STRONG&gt;Declarative Rule Condition&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Next, expand the Condition property and set the &lt;STRONG&gt;ConditionName&lt;/STRONG&gt; to &lt;EM&gt;CheckForZero&lt;/EM&gt;.&lt;/LI&gt;
&lt;LI&gt;Now click the ellipsis (...) to create a new rule:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws14.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;The result should look like:&lt;BR&gt;&lt;BR&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws15.jpg"&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#008000&gt;&lt;U&gt;Tip:&lt;/U&gt; Take a look at the Divider.rules file in the Solution Explorer. This file contains the declarative rule. The reason I've chosen for&amp;nbsp;a "declarative rule condition" is to show you this feature (and the underlying XML); however, in this situation a "code condition" would be better because the condition won't ever change. Declarative rule conditions and code conditions both have pros and cons, but this falls outside the scope of this post.&lt;/FONT&gt;&lt;BR&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Drag and drop a &lt;STRONG&gt;WebServiceFaultActivity&lt;/STRONG&gt; into the left (&lt;EM&gt;isZero&lt;/EM&gt;) branch.&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Set its &lt;STRONG&gt;InputActivityName&lt;/STRONG&gt; to &lt;EM&gt;webServiceInput1&lt;/EM&gt;.&lt;/LI&gt;
&lt;LI&gt;Next, you'll have to set the &lt;STRONG&gt;Fault&lt;/STRONG&gt; property. In order to do this, first switch to the code view and add the following:&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ArgumentException&lt;/FONT&gt;&lt;FONT size=2&gt; divisionByZero = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ArgumentException&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"Division by zero."&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;ArgumentException&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; DivisionByZero&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; divisionByZero; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; set&lt;/FONT&gt;&lt;FONT size=2&gt; { divisionByZero = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;Now you can set the Fault property to &lt;EM&gt;DivisionByZero&lt;/EM&gt;.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;P&gt;In the right branch (&lt;EM&gt;nonZero&lt;/EM&gt;), add a &lt;STRONG&gt;CodeActivity&lt;/STRONG&gt; and call it &lt;EM&gt;divide&lt;/EM&gt;. Add an &lt;STRONG&gt;ExecuteCode&lt;/STRONG&gt; handler with the following piece of code:&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; divide_ExecuteCode(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;EventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; result = a / b;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;Move the &lt;EM&gt;webServiceOutput1&lt;/EM&gt; activity below the &lt;EM&gt;divide&lt;/EM&gt; activity in the right branch (&lt;EM&gt;nonZero&lt;/EM&gt;).&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;If you've done the jobs above correctly, you should see this:&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws13.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;Get it published&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Time to start the web service creation and publication. Right-click the WorkflowViaWS project in the Solution Explorer and choose &lt;STRONG&gt;Publish as Web Service&lt;/STRONG&gt;:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws08.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This will create an ASP.NET Web Site called &lt;STRONG&gt;WorkflowViaWS_WebService&lt;/STRONG&gt; and add it to the current solution:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws16.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;As you can see a web.config file was created (it should pop up immediately after completion of the "Publish as Web Service" action). &lt;FONT color=#008000&gt;In there you'll see some interesting regions such as:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#800000 size=2&gt;WorkflowRuntime&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;WorkflowServiceContainer&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Services&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;add&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;type&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;add&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;type&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;System.Workflow.Runtime.Hosting.DefaultWorkflowCommitWorkBatchService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;Services&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;WorkflowRuntime&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Arial size=2&gt;More information about these two services (which have to do with threading) can be found in the Windows SDK. &lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;You'll also see an HttpModule being hooked in:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;httpModules&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;add&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;type&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;System.Workflow.Runtime.Hosting.WorkflowWebHostingModule, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;WorkflowHost&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;httpModules&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial color=#008000 size=2&gt;This module (&lt;STRONG&gt;WorkflowWebHostingModule&lt;/STRONG&gt;) is responsible to maintain (read/write) a client cookie that holds the workflow's instance identifier (a GUID that uniquely represents the workflow instance the user is connected to). This allows multiple web method calls to be part of one workflow instance.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#008000 size=2&gt;Finally there are references to the System.Workflow.* assemblies:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#800000 size=2&gt;add&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;assembly&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;System.Workflow.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;add&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;assembly&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;add&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;assembly&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The web service file (called &lt;STRONG&gt;WorkflowViaWS.Divider_WebService.asmx&lt;/STRONG&gt; but renameable) has a fairly short definition:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;lt;%&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;@&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;WebService&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Class&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="WorkflowViaWS.Divider_WebService"&lt;/FONT&gt;&lt;FONT size=2&gt; %&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial color=#008000 size=2&gt;Geeky readers might consider to ildasm the WorkflowViaWS.dll file that was dropped in the Bin folder:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws09.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#ff0000 size=2&gt;&lt;STRONG&gt;Hit F5 and run&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Eager to see what you've created? Just hit F5 (when you're somewhere inside the ASP.NET Web Site in order to have the website as startup project) and choose the add debugging&amp;nbsp;configuration to web.config (this&amp;nbsp;might be useful if you decide to play with breakpoints in the workflow). The&amp;nbsp;&lt;STRONG&gt;built-in ASP.NET Development Server&lt;/STRONG&gt; will get launched:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws10.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Finally the web service page will be displayed in the browser:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws11.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Click on &lt;STRONG&gt;Divide&lt;/STRONG&gt; to test the web service and enter the values 10 and 20. The result should be - help where is my calc.exe? - 0.5:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws12.jpg"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#008000&gt;&lt;U&gt;Note:&lt;/U&gt; If you try to invoke the web service more than once in the same session, you'll see the following error.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face="Courier New" size=2&gt;System.InvalidOperationException: The workflow hosting environment does not have a persistence service as required by an operation on the workflow instance &amp;amp;quot;21b04980-9926-4b35-a87f-3d1c98b3a987&amp;amp;quot;.&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial color=#008000 size=2&gt;This is normal because of our configuration. Recall the &lt;STRONG&gt;WorkflowWebHostingModule &lt;/STRONG&gt;HttpModule that keeps track of the workflow instance identifier in a cookie on the web client. In between calls from the same session the system needs to be able to persist the workflow instance data to disk. Because we didn't configure a persistence service, this fails. Persistence services will be covered in a separate post later on.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=2&gt;What about the &lt;STRONG&gt;fault&lt;/STRONG&gt;? Restart your browser and open the web service page again. Now try to make a call with parameters a=10 and b=0. When invoking the service, you'll end up with an &lt;STRONG&gt;HTTP 500 Internal Server Error&lt;/STRONG&gt;. If you want to see the exception that was sent in the fault, create a little web service client application (e.g. a console application) like this:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;Program&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Main(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;[] args)&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; localhost.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Divider_WebService&lt;/FONT&gt;&lt;FONT size=2&gt; ws = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; localhost.&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Divider_WebService&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;();&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; double&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt; res = ws.Divide(10, 0);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Exception&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt; ex)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial color=#008000 size=2&gt;I assume everyone knows how to add a web service reference to an existing web service and how to use the proxy object. There's one caveat however: if you restart the ASP.NET Development Server that comes with Visual Studio 2005, it will likely listen on another random port. The web service proxy will then be invalid, unless you change the Url property on the proxy object to reflect the current URL to the web service (&lt;FONT face="Courier New"&gt;&lt;A href="http://localhost:&lt;port&gt;/WorkflowViaWS_WebService/WorkflowViaWS.Divider_WebService.asmx"&gt;http://localhost:&amp;lt;port&amp;gt;/WorkflowViaWS_WebService/WorkflowViaWS.Divider_WebService.asmx&lt;/A&gt;&lt;/FONT&gt;). &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#008000 size=2&gt;You can copy the application to an &lt;STRONG&gt;IIS&lt;/STRONG&gt; machine too of course, but keep in mind the same version (= CTP build) of WF (and hence, .NET Framework 3.0) needs to be present on the web server machine. If you're using your own pc as IIS web server, there shouldn't be a problem if configuration is correct (ASP.NET 2.0 is registered - cf. aspnet_regiis.exe - and - in W2K3 - the web service extension is allowed). For Vista users some experience with IIS 7 might be helpful although it's pretty plug-and-play.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;That said, the result of a debugging session should be like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://www.bartdesmet.net/images/wfws17.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=3&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Exposing a workflow through simple ASP.NET 2.0 web services is no rocket science. In this post you saw the basics of this; further posts in this &lt;A HREF="/blogs/bart/archive/category/1004.aspx"&gt;workflow series&lt;/A&gt;&amp;nbsp;will cover more advanced scenarios with workflow persistence and the use of WCF as a WF host.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Keep up the good WF-work!&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://community.bartdesmet.net/aggbug.aspx?PostID=4388" width="1" height="1"&gt;</description><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/Windows+Workflow+Foundation+_2800_WF_2900_/default.aspx">Windows Workflow Foundation (WF)</category><category domain="http://community.bartdesmet.net/blogs/bart/archive/tags/.NET+Framework+3.0+_2800_WinFX_2900_/default.aspx">.NET Framework 3.0 (WinFX)</category></item></channel></rss>