Handling WorkflowRuntime events for IIS hosted WCF + WF services

The WorkflowRuntime class has a host of interesting methods and useful events. Events such as Completed, Perssited, Idled are invaluable when debugging and in understanding how a workflow instance is behaving.
These events are easily accessible when self hosting the runtime since you can just hook up event handlers for these events and react to these events as you see fit.
But, when the workflow runtime is hosted in IIS/WAS/Cassini host, you don’t have a direct handle to the runtime for hooking up these events.
The .svc file for the WCF service contains the WorkflowServiceHostFactory that WCF uses for servicing workflow service requests.

 
  1. <%@ ServiceHost Language="C#"   
  2. Debug="true"   
  3. Service="RequestWFServiceLib.ApprovalWorkflow"  
  4. Factory="System.ServiceModel.Activation.WorkflowServiceHostFactory"%>  

We can easily subclass WorkflowServiceHostFactory and replace the Factory attribute in the .svc file with a custom implementation of this class where in we override the CreateServiceHost Method and get a handle to the WorkflowRuntime and hook up the event handlers we need.

 
  1.    public class CustomWorkflowServiceHost : WorkflowServiceHostFactory  
  2. {  
  3.   
  4.        public override System.ServiceModel.ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)  
  5.        {  
  6.            ServiceHostBase hostBase = base.CreateServiceHost(constructorString, baseAddresses);  
  7.            WorkflowRuntimeBehavior runtimeBehavior = hostBase.Description.Behaviors.Find<WorkflowRuntimeBehavior>();  
  8.            WorkflowRuntime runtime = runtimeBehavior.WorkflowRuntime;  
  9.            runtime.WorkflowIdled += runtime_WorkflowIdled;  
  10.            runtime.Started += runtime_Started;  
  11.            runtime.Stopped += runtime_Stopped;  
  12.            runtime.WorkflowStarted += runtime_WorkflowStarted;  
  13.            runtime.WorkflowSuspended += runtime_WorkflowSuspended;  
  14.            runtime.WorkflowUnloaded += runtime_WorkflowUnloaded;  
  15.            runtime.WorkflowCreated += runtime_WorkflowCreated;  
  16.            runtime.WorkflowTerminated += runtime_WorkflowTerminated;  
  17.            runtime.WorkflowResumed += runtime_WorkflowResumed;  
  18.            runtime.WorkflowPersisted += runtime_WorkflowPersisted;  
  19.            runtime.WorkflowLoaded += runtime_WorkflowLoaded;  
  20.            runtime.WorkflowCompleted += runtime_WorkflowCompleted;  
  21.            runtime.WorkflowAborted += runtime_WorkflowAborted;  
  22.            return hostBase;  
  23.   
  24.        }  
  25.   
  26.        void runtime_WorkflowAborted(object sender, WorkflowEventArgs e)  
  27.        {  
  28.            Debug.WriteLine(string.Format("WorkflowInstance {0} Aborted", e.WorkflowInstance.InstanceId.ToString()));  
  29.        }  
  30.   
  31.        void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)  
  32.        {  
  33.            Debug.WriteLine(string.Format("WorkflowInstance {0} Completed", e.WorkflowInstance.InstanceId.ToString()));  
  34.        }  
  35.   
  36.        void runtime_WorkflowLoaded(object sender, WorkflowEventArgs e)  
  37.        {  
  38.            Debug.WriteLine(string.Format("WorkflowInstance {0} Loaded", e.WorkflowInstance.InstanceId.ToString()));  
  39.        }  
  40.   
  41.        void runtime_WorkflowPersisted(object sender, WorkflowEventArgs e)  
  42.        {  
  43.            Debug.WriteLine(string.Format("WorkflowInstance {0} Persisted", e.WorkflowInstance.InstanceId.ToString()));  
  44.        }  
  45.   
  46.        void runtime_WorkflowResumed(object sender, WorkflowEventArgs e)  
  47.        {  
  48.            Debug.WriteLine(string.Format("WorkflowInstance {0} Resumed", e.WorkflowInstance.InstanceId.ToString()));  
  49.        }  
  50.   
  51.        void runtime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)  
  52.        {  
  53.            Debug.WriteLine(string.Format("WorkflowInstance {0} Terminated", e.WorkflowInstance.InstanceId.ToString()));  
  54.        }  
  55.   
  56.        void runtime_WorkflowCreated(object sender, WorkflowEventArgs e)  
  57.        {  
  58.            Debug.WriteLine(string.Format("WorkflowInstance {0} Created", e.WorkflowInstance.InstanceId.ToString()));  
  59.        }  
  60.   
  61.        void runtime_WorkflowUnloaded(object sender, WorkflowEventArgs e)  
  62.        {  
  63.            Debug.WriteLine(string.Format("WorkflowInstance {0} Unloaded", e.WorkflowInstance.InstanceId.ToString()));  
  64.        }  
  65.   
  66.        void runtime_WorkflowSuspended(object sender, WorkflowSuspendedEventArgs e)  
  67.        {  
  68.            Debug.WriteLine(string.Format("WorkflowInstance {0} Suspended", e.WorkflowInstance.InstanceId.ToString()));  
  69.        }  
  70.   
  71.        void runtime_WorkflowStarted(object sender, WorkflowEventArgs e)  
  72.        {  
  73.            Debug.WriteLine(string.Format("WorkflowInstance {0} Started", e.WorkflowInstance.InstanceId.ToString()));  
  74.        }  
  75.   
  76.        void runtime_Stopped(object sender, WorkflowRuntimeEventArgs e)  
  77.        {  
  78.            Debug.WriteLine("Workflow runtime Stopped");  
  79.        }  
  80.   
  81.        void runtime_Started(object sender, WorkflowRuntimeEventArgs e)  
  82.        {  
  83.            Debug.WriteLine("Workflow runtime Started");  
  84.        }  
  85.   
  86.        void runtime_WorkflowIdled(object sender, WorkflowEventArgs e)  
  87.        {  
  88.            Debug.WriteLine("Workflow runtime Idled");  
  89.        }  
  90. }  

the .svc file is updated to include the name of our custom implementation. That’s all there is to it.

 
  1. <%@ ServiceHost Language="C#"   
  2. Debug="true"   
  3. Service="RequestWFServiceLib.ApprovalWorkflow"  
  4. Factory="RequestWFServiceLib.CustomWorkflowServiceHost"%>  

kick it on DotNetKicks.com

Print | posted @ Sunday, April 26, 2009 10:38 PM

Comments on this entry:

No comments posted yet.

Post A Comment
Title:
Name:
Email:
Comment:
Verification: