Let's cut to the chase, here is what needs to be done to track the events we want:
Subclass from TrackingParticipant and override its Track method. Within this Track method we'll look only for TrackingRecords of type WorkflowInstanceRecord, since we only want to capture
workflow level events.
NOTE: you can also attach to activity
and custom level events but that's out of the scope of this blog post. I
recommend this article for a more in depth description of Tracking: http://www.codeproject.com/KB/WF/WF4Extensions.aspx
If you want your application to
"react" to particular workflow events, we only need to inspect
the WorkflowInstanceRecord.State property. The following sample code is
a generic template you can use with all the possible states I've encountered so
far:
using System.Activities.Tracking;
public class WorkflowStateTrackingParticipant :TrackingParticipant
{
protected override void Track(TrackingRecord record, TimeSpan timeout)
{
WorkflowInstanceRecord workflowInstanceRecord
= record as WorkflowInstanceRecord;
if(workflowInstanceRecord != null)
{
switch(workflowInstanceRecord.State)
{
case "Started": break;
case "Aborted": break;
case "Canceled": break;
case "Completed": break;
case "Deleted": break;
case "Idle": break;
case "Persisted": break;
case "Resumed": break;
case "Successful": break;
case "Suspended": break;
case "Terminated": break;
case "UnhandledException": break;
case "Unloaded": break;
case "Unsuspended": break;
case "Aborted": break;
case "Canceled": break;
case "Completed": break;
case "Deleted": break;
case "Idle": break;
case "Persisted": break;
case "Resumed": break;
case "Successful": break;
case "Suspended": break;
case "Terminated": break;
case "UnhandledException": break;
case "Unloaded": break;
case "Unsuspended": break;
default: break;
}
}
}
}
To use this class, we need
to add it to the WorkflowExtensions collection of our WorkflowServiceHostFactory; we do this by subclassing from it and
overriding the CreateWorkflowServiceHost methods:
public class CustomWorkflowServiceHostFactory : WorkflowServiceHostFactory
{
protected override WorkflowServiceHost CreateWorkflowServiceHost(System.Activities.Activity activity, Uri[] baseAddresses)
{
WorkflowServiceHost host = base.CreateWorkflowServiceHost(activity, baseAddresses);
host.WorkflowExtensions.Add(new WorkflowStateTrackingParticipant());
return host;
}
protected override WorkflowServiceHost CreateWorkflowServiceHost(WorkflowService service, Uri[] baseAddresses)
{
WorkflowServiceHost host = base.CreateWorkflowServiceHost(service, baseAddresses);
host.WorkflowExtensions.Add(new WorkflowStateTrackingParticipant());
return host;
}
}
Finally, we need to
indicate this CustomWorkflowServiceHostFactory, instead of the default one, in your Web.config or .svc
files (depending on your particular implementation). In my case, I create my
.svc definition files from the .xamlx workflows, dynamically, through
Web.config via the serviceHostingEnvironment section:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="MyWorkflowService.svc"
service="Workflow.xamlx"
factory="CustomWorkflowServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
Verify you can hit your
.svc from a browser and you're done.
That's it, hopefully this post can help people save more than a few minutes of research.
No comments:
Post a Comment