Second Stanza

December 29, 2008

WorkflowServiceHost Limitations and Work-Arounds

Filed under: WorkFlow — Tags: , — dfbaskin @ 6:37 pm

The implementation of the WorkflowServiceHost class apparently requires a single instance of the class to be created for each type of workflow being hosted. This also means that a separate workflow runtime will be created for each of these instances. This doesn’t seem to be very efficient since a single workflow runtime can handle multiple types of workflows. Multiple workflow runtimes seem like a waste of resources.

So I asked around about this.

Kenn Scribner, author of Microsoft Windows Workflow Foundation Step by Step, answers:

The short answer is you are correct, and a lot of people aren’t happy about this limitation. I’ve heard rumors this might be corrected in .NET 4.0, but just rumors.

An alternative is to write your own host class, if you’re of a mind to do so…

Paul Mehner adds his thoughts:

I was not aware that send/receive activities require a new runtime and I am thinking that this is likely just a configuration issue. I assure you that you do not want multiple hosts no matter what. That would be a ridiculous constraint if it proved to be true, and I plan to investigate this later tonight if my time permits (it likely won’t but I will try). In general, you should have only one workflow runtime for a single AppDomain, and that runtime can easily service many types of workflows.

BTW: I completely avoid using the send/receive activities. In point of fact, I have _never_ used them in a production application (only for training and demo purposes). These activities couple a workflow with a need to be used in a service host, thus preventing a workflow from being used independent of its hosting environment. I like a better separation of concerns than this model allows. I also like business developers to stay focused on their own business implementations without worrying about the network plumbing that services developers are concerned with (who likewise don’t want to be burdened with having to understand business rules and processes). I _always_ create my own service host, which itself hosts a singleton of the WF runtime. I can then run an infinite number of differing workflow types based on the service operations that are called. I can provide additional sample code if you would like… just ask. Here’s a starter though…

   [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
   public class EpukServiceBus : ServiceBase, IEpukServiceBus
       public EpukServiceBus() : base()
             Factory factory = new Factory();

And later adds:

The workflow runtime is designed to support multiple workflow types running simultaneously. That’s a fact you can bank on. If the ReceiveActivity violates that principle by introducing a need for multiple workflow runtimes for each workflow type, then that product manager REALLY screwed things up. I still haven’t had time to prove or disprove that assertion, and I will be traveling from the holidays back home today (and with pass conditions in the PNW — likely tomorrow as well), so it’s not likely this week.

Is the workflow we are talking about a sequential workflow or a state machine? It sounds to me like this is a state machine workflow, so I think I would probably just drive it off of the events that cause the state changes. I would expose the state change events through the abstraction of different operations on my operation contract, and I would pass the data into the workflow through the corresponding custom EventArgs. An external caller would call an operation on the service that would raise the appropriate state transition event on the workflow, and pass in the relevant data. I have used this pattern on several production systems with great success. Of course a single operation on the service contract could examine the data and then raise the appropriate event (if that makes the interface simpler for the caller, like the facade pattern described below).

I dislike the entire concept of the Receive/Send activities. I find that they too often violate my sense of separation of concerns. If they are really wired with the limitations that people are blogging about, then I find them to be much worse than that.

This forum post also confirms the limitation.

I agree that there should be a good separation of concerns in a production implementation (as Paul discusses above). For a project that I am working on, I ended up defining workflow events but created a service layer that fires the events. This separates communications issues from the actual hosting of the workflow.

Another idea, suggested in the forums post above, was to create a single workflow with a number of receive activities that route incoming requests to other workflows (using the Facade pattern). This is an interesting idea as well, but I have not tried it.

December 27, 2008

Unit Testing Workflow Activities

Filed under: .NET Development, WorkFlow — Tags: , — dfbaskin @ 10:30 pm

I’ve been using a technique similar to the code below to unit test custom workflow activities.

using System;
using System.Collections.Generic;
using System.Workflow.Runtime;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime.Hosting;
using System.Workflow.Runtime.Tracking;
using System.Configuration;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TrackingError
    public class TestActivity : Activity
        public static readonly DependencyProperty MessageProperty = DependencyProperty.Register( "Message", typeof( String ), typeof( TestActivity ) );

        public string Message
            get { return (String)GetValue( MessageProperty ); }
            set { SetValue( MessageProperty, value ); }

        protected override ActivityExecutionStatus Execute( ActivityExecutionContext executionContext )
            Message = "Success";
            return ActivityExecutionStatus.Closed;

    public class ShowTrackingError
        public ShowTrackingError()

        private TestContext testContextInstance;

        public TestContext TestContext
            get { return testContextInstance; }
            set { testContextInstance = value; }

        private static string ConnectionString
            get { return ConfigurationManager.ConnectionStrings["WorkFlowDB"].ConnectionString; }

        private WorkflowRuntime workflowRuntime;
        private AutoResetEvent resetEvent;
        private Dictionary<String, Object> outputArgs;
        private bool completedWorkflow;

        public void CreateWorkFlowEnvironment()
            bool startedWorkflow = false;
                resetEvent = new AutoResetEvent( false );
                outputArgs = null;
                completedWorkflow = false;

                workflowRuntime = new WorkflowRuntime();

                SharedConnectionWorkflowCommitWorkBatchService sharedConnService = new SharedConnectionWorkflowCommitWorkBatchService( ConnectionString );
                workflowRuntime.AddService( sharedConnService );

                SqlWorkflowPersistenceService persistService = new SqlWorkflowPersistenceService( ConnectionString );
                workflowRuntime.AddService( persistService );

                SqlTrackingService trackingService = new SqlTrackingService( ConnectionString );
                workflowRuntime.AddService( trackingService );

                workflowRuntime.WorkflowCompleted += delegate( object sender, WorkflowCompletedEventArgs e ) {
                    outputArgs = e.OutputParameters;
                    completedWorkflow = true;
                workflowRuntime.WorkflowTerminated += delegate( object sender, WorkflowTerminatedEventArgs e ) {
                workflowRuntime.WorkflowAborted += delegate( object sender, WorkflowEventArgs e ) {

                startedWorkflow = true;
                if( !startedWorkflow )
                    if( workflowRuntime != null )
                        workflowRuntime = null;

        public void ShutDownWorkFlowEnvironment()
            if( workflowRuntime != null )
                    workflowRuntime = null;

        public void UnitTestWorkflowActivity()
            Assert.IsNotNull( workflowRuntime );

            WorkflowInstance wfInst = workflowRuntime.CreateWorkflow( typeof( TestActivity ) );
            Assert.IsNotNull( wfInst );


            resetEvent.WaitOne( 5000 );

            Assert.IsTrue( completedWorkflow );
            Assert.IsNotNull( outputArgs );
            Assert.AreEqual( "Success", (String)outputArgs["Message"] );

(Note that common code like the methods marked with the TestInitialize and TestCleanup attributes are actually in a shared based class, but included in the test class here for our discussion.)

However, the above unit test does not work. The activity is aborted so the completedWorkflow value is never set to true. This behavior is apparent both in this unit test as well as in an application that runs the single activity. Perhaps I’ve misunderstood something, but I believe this should work. The activity should not abort.

It appears that the SqlTrackingService class expects a CompositeActivity, not a Activity-derived class since the error written to the log is:

System.Workflow.Runtime.Hosting Error: 0 : SharedConnectionWorkflowCommitWorkBatchService caught
      exception from commitWorkBatchCallback: System.InvalidCastException: Unable to cast object
      of type 'TrackingError.TestActivity' to type 'System.Workflow.ComponentModel.CompositeActivity'.
   at System.Workflow.Runtime.Tracking.SqlTrackingService.SqlTrackingChannel.InsertWorkflow(DbCommand command, Guid workflowInstanceId, Type workflowType, Activity rootActivity)
   at System.Workflow.Runtime.Tracking.SqlTrackingService.SqlTrackingChannel.ExecuteInsertWorkflowInstance(DbCommand command)
   at System.Workflow.Runtime.Tracking.SqlTrackingService.SqlTrackingChannel.Commit(Transaction transaction, ICollection items)
   at System.Workflow.Runtime.WorkBatch.PendingWorkCollection.Commit(Transaction transaction)
   at System.Workflow.Runtime.WorkBatch.Commit(Transaction transaction)
   at System.Workflow.Runtime.VolatileResourceManager.Commit()
   at System.Workflow.Runtime.WorkflowExecutor.DoResourceManagerCommit()
   at System.Workflow.Runtime.Hosting.SharedConnectionWorkflowCommitWorkBatchService.CommitWorkBatch(CommitWorkBatchCallback commitWorkBatchCallback)

Several work-arounds make this unit test pass:

  • Instead of derving the custom activity from the Activity class, it can be derived from CompositeActivity.
  • The activity can be wrapped in some other activity, such as the TransactionScopeActivity. However, the properties used to test the results of the workflow must be propagated out to the wrapping activity.
  • The SqlTrackingService workflow runtime service can be removed.

I’ve opened a Microsoft Connect feedback item here. A Microsoft forums post is here.

November 12, 2008

Windows WorkFlow Activity Data

Filed under: .NET Development, WorkFlow — Tags: — dfbaskin @ 12:54 am

One of the first questions I had about Windows Workflow (in .NET 3.0) was how data was moved around between workflow activities. Activities, of course, are the meat of a workflow process in that they define the actual work a workflow will address. So if one activity picks up a useful data value that some other activity will later need, what technique should be used to pass this data between these activities?

Windows Workflow Foundation provides several features that aid in accomplishing this task:

  • Activity Properties – each activity may publish it’s own bindable set of properties that can be used as input and output parameters for the activity.
  • Workflow Properties – the workflow itself can publish it’s own set of properties.
  • Declarative Binding – using dependency properties, properties from one activity can be automatically bound to properties on other activities.
  • Workflow Navigation – From within an activity, you can navigate the hierarchy of a workflow process in order to find specific instances of other activities that may have information you need.

These features give you multiple options for moving activity data around within a workflow. However, you must be careful in your implementation since, for example, workflows allow parallel processing and you must be sure to get to the activity instance that you really want. MSDN published a very useful article about these and other related issues here.

To me, the best option is to use declarative binding, for two reasons. The first reason is that declarative binding eliminates any ambiguity about which activity instance you are binding to.

The second reason is to abstract your activity objects from your workflow. When navigating the hierarchy of the workflow, you are making assumptions about how the workflow is structured. Using bindings on properties allows the activity to be more stand-alone and more likely to be reusable. And of course, it allows easier unit testing of the activity.

Create a free website or blog at