How to get workflow data/properties at runtime

I've seen many people in the forums trying to figure out the best way to get data from a workflow at runtime.  The root of the problem lies in the fact that while you can get a handle to a WorkflowInstance from the runtime, this is really a template and does not contain the values of properties on the workflow.  It is a common need to get the current state of your process, or get values from the class. 
 
One solution is to use the local communications activities and call back to the host and have a local service manage the values.  But, who wants to drop a bunch of CallExternalMethod activities in all of their workflows.  No the answer, not surprisingly, lies with tracking. 
 
Tracking in workflow provides so much power and flexibility to extract data that you are interested in. I've created a custom tracking service which tracks the workflow properties at runtime and stores them in a dictionary in the service.  When you want to get the current property values for a workflow, you get the tracking service from the runtime, then ask it for the properties which you get back as a Dictionary<string, object> just like the parameters you passed into the workflow. 
 
There are two keys to getting this work and both revolve around the tracking profile.  First, it is important to know that when you define an ActivityTrackPoint, you can add data extracts which define the data to extract and send to the tracking channel.  But those extracts can either be activity extracts, or workflow extracts.  So, I define an activity track point to track all activities on close and add Workflow level extracts to pull the properties off of the workflow at that point.  The second key piece is figuring out what properties are available on each workflow type.  This service would be pretty limited if it were tied to a specific workflow type.  Instead, when the profile is created based on a workflow type, I reflect on the type to get the public properties defined in this type (not the base classes though you can do that too) and build the extract definitions from them. 
 
So, when a workflow is run, the profile is created indicating that on each activity closed, the properties of the workflow should be sent to the tracking channel.  In the channel, I simply update the dictionary of values stored in the service.  Finally, when an instance completes or terminates, I remove the values from the dictionary. 
 
You could track more often by using other statuses on the activity tracking location, but beware of the overhead tracking may add in these cases. 
 
I hope this is helpful.  As always, comments and feedback are welcome. 

Posted Nov 25 2006, 09:22 PM by matt-milner

Comments

Christopher Steen wrote Link Listing - November 29, 2006
on 11-29-2006 10:18 PM
Creating CSS Friendly Websites with ASP.NET 2.0 [Via: ] Lollygag: Latest non-Atlas .NET Framework [Via:...
Atul Gupta wrote re: How to get workflow data/properties at runtime
on 12-01-2006 2:00 AM
This sure sounds useful. Need to try it myself and will that soon. Thanks for the tips
Peter Liu wrote re: How to get workflow data/properties at runtime
on 12-05-2006 7:12 AM
It's a great blog, and I also enjoy your MSDN article. As you mentioned at the end, it's not efficient if there are a lot of tracking points at the activity. I don't understand why it suddenly becomes so difficult for the basic Windows event-driven programming in the Workflow Foundation. Also for creating a simple message box in an activity, I need to use custom runtime service. It must be easier than I did.
Matt Milner wrote re: How to get workflow data/properties at runtime
on 12-06-2006 1:26 PM
Peter,
The event driven model in WF is there to handle the workflow programming model. That is, it is possible that your workflow will be taken out of memory or persisted and therefore direct eventhandlers would be lost. The indirection, using ExternalDataExchange, helps to manage that while keeping you from having to code low level communication APIs.
As for the MessageBox, you should be able to do that right within your workflow (with a code activity for example). However, the better model would be to use a local communication service as this allows you to use interface based programming. Your workflow calls a method on an interface to send a message to the UI, and your implementation decides whether to use a message box, asp.net page, the console, or some other technique to display the data. In this way, your workflow is not bound to a host type.
Thanks for reading and I hope this helps.
Javier Romero wrote Links para esta semana.
on 02-22-2007 8:49 AM
Creating CSS Friendly Websites with ASP.NET 2.0 [Via: ] Lollygag: Latest non-Atlas .NET Framework [Via:
Baski wrote re: How to get workflow data/properties at runtime
on 04-02-2007 12:12 PM
I used your property tracking service to read and update properties. Once the instance is persisted all the properties are removed from property tracking object(workflowParameters). How can I re-read those properties back for a given workflow instance ?
Matt Milner wrote re: How to get workflow data/properties at runtime
on 04-02-2007 5:53 PM
Baski,
I'm not sure how you updated the properties, but if you are using the workflow definition, you are only updating the template. In order to change the state/properties of the workflow, you'll need to do this from an activity.
In regards to the service and durability, the implementation I provided didn't provide a model for storing those values to disk. The tracking service should, however, reset the property values as soon as an activity closes.
If you want to store the values through a persistence cycle, then you should implement the IPendingWork and add an item to the WorkBatch on each update. When it comes time ot commit, you can just save the latest values to a database somewhere.
baski wrote re: How to get workflow data/properties at runtime
on 04-09-2007 6:23 AM
Matt thank you so much for your response.

I use SqlWorkflowPersistenceService, I assume internally SqlWorkflowPersistenceService implements IPendingWork interface. So do I have to implement the IPendingwork interface to store data or I can directly use tracking service to retrive the properties from persistant database ?
Matt Milner wrote re: How to get workflow data/properties at runtime
on 04-09-2007 8:09 AM
Baski,
The persistence database is doing to contain the state as a blob, so you won't be able to query and get the individual properties you want. If you need the actual values of the properties to be persistent so that you can get them between runtime restarts, you'll need to persist those values somewhere that you can query them.

Baski wrote re: How to get workflow data/properties at runtime
on 04-09-2007 9:00 AM
Thansk again, the interesting aspect I saw when I was debugging by workflow, eventhough I was not able to get the properties between persistance, as soon as I raise some event on workflow all my properties where initilized. Is ther any genric event in the workflow activity which I can raise , so that I can reinitilaize the properties when needed. If I'm not making any sense, do I have to implment IPendingwork on my data service class or PropertyTracking service class ?

Thanks again.
Matt Milner wrote re: How to get workflow data/properties at runtime
on 04-10-2007 6:58 AM
Baski,
That's becuase when you raise an event to your workflow, an activity completes / closes which is where the tracking service gets notified of the data to track.

If you implement IPendingWork, it would be implemented on the tracking channel most likely. THen in the send method, you might write the data to the dictionary as is currently happening and add an item to the current work batch. Then when the workflow persists, your commit method will be called and you can save the data to a simple database.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?