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

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.
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.
thomasvdb wrote re: How to get workflow data/properties at runtime
on 10-14-2008 7:27 AM

I tried your code but when I look at the Send-method and debug through it, the record.Body contains more then 5000 items (including FaultHandlerActivity etc...)!

And it gives an error that a key is already used... prolly because of the FaultHandlerActivities etc...)

matt-milner wrote re: How to get workflow data/properties at runtime
on 10-14-2008 10:55 AM

Thomas,

I can't reproduce that issue on my end.  Did you make any changes to the tracking service code?  If you can send me a sample, I'll try to help you troubleshoot.  The service should only get the public properties declared on your workflow type, so the activities collection should not show up as that is declared on the base type.  

Matt

thomasvdb wrote re: How to get workflow data/properties at runtime
on 10-15-2008 3:10 AM

I found my problem... I needed to convert your C# code to VB.NET and made a mistake.

Stupid!

Sorry for the trouble!

And thanks for this great piece of code!

Eugenio Serrano wrote re: How to get workflow data/properties at runtime
on 10-15-2008 5:30 PM

Good Article !!

Thanks !

thomasvdb wrote re: How to get workflow data/properties at runtime
on 10-16-2008 9:17 AM

Hmm... when my ASP.NET application restarts (reads all configuration from Global.asax again) the properties are empty.

What's the best way to get the properties again? The workflows are persisted yet...

matt-milner wrote re: How to get workflow data/properties at runtime
on 10-16-2008 9:41 AM

Thomas, please read the comments and exchange between myself and BASKI on this post as it discusses this issue and how the sample works.  The properties on the service are only populated when an activity closes, and are not kept in memory or stored in a persisted state.  You could certainly implement that, but I didn't for this sample.  So you won't see the values until another activity executes and closes.

thomasvdb wrote re: How to get workflow data/properties at runtime
on 10-17-2008 12:36 AM

One question though...

There is no other way then saving this (the properties in the Dictionary) to a database (or a file)?

matt-milner wrote re: How to get workflow data/properties at runtime
on 10-20-2008 10:02 AM

You can get properties from the workflow through tracking, but there isn't a great way that comes to mind to get them when the workflow is loaded.  you can register a workflowtrackingevent on the profile, but you don't have the ability to do extracts based on those events, if I remember correctly. You can have your tracking service register for workflow loaded events on the runtime, and then load the properties from some durable store, assuming your tracking service has saved them out somewhere.

There are probably other options, such as using a dependency proeprty on the workflow instance, but this is the approach that comes to mind first.  

Andreas wrote re: How to get workflow data/properties at runtime
on 11-12-2008 7:11 AM

Great article Matt! It saved me lots of time. Althogh I have a question...

I have a main workflow with a couple of "sub workflows" in series. The sub workflow has a public dependency property. Is it possible to get the value from these properties from the main workflow? I have the workflowInstanceId for the main workflow but cannot get a handle to the sub workflows.

Example:

MAIN WORKFLOW:

      Start

         |

  SubWorkflow  --> Extract the dependency parameter

         |

  Sub Workflow --> Extract the dependency parameter

         |

      Exit

matt-milner wrote re: How to get workflow data/properties at runtime
on 11-12-2008 1:11 PM

Andreas,

In the call to GetTrackingChannel on the tracking service, an instance of the TrackingParameters class is passed in, which I believe my sample passes to the TrackingChannel.  That class includes the instance id of the calling (parent) workflow instance.  So, when tracking a child activity, you would need to do the following:

1) make sure the profile for that type gets registered (in the sample all types use the same profile so this may not be an issue).

2) in the Send method implementation of the tracking channel, you can check the properties of the TrackingParameters to see if there is a parent workflow id.  

3) update the send logic as you see fit to use that parent id to store the data.  In the simple case you might find that data in the dictionary on the tracking service, then add a item with some key name combining information about the child workflow instance with the property name, and the value.

now you can look in the tracking service for a particular parent workflow and find data on the child workflows.  

Hope this is helpful,

Matt

Andreas wrote re: How to get workflow data/properties at runtime
on 11-13-2008 7:05 AM

Thanks a million Matt.With you help here and the fantastic artice about Tracking Service you wrote in MSDN I finally got it  to work. My problem now is this.

From what I understand you have to set the ActivityTrackingLocation (ATL) of your ActivityTrackPoint. In the ATL you define when the property/data should be tracked. For example ActivityExecutionStatus.Closed. But I want to update the data when an internal event is triggered in the activity and not any of the "pre defined" ActivityExecutionStatus events. Is that possible?

To clarify my question. Is it possible to do something like this.

ActivityTrackingLocation location = new ActivityTrackingLocation(typeof(UnitActivity), false, new ActivityExecutionStatus[] { UnitActivity.StatusUpdated });

matt-milner wrote re: How to get workflow data/properties at runtime
on 11-13-2008 8:52 AM

Andreas,

what you want is to use a UserTrackPoint instead of an ActivityTrackPoint.  It still lets you specify the activity type but rather than being dependent on the activity status change, it can use a Key or named value as the trigger.  Then in your activity, you will have to add a call  to the TrackData method found in the Activity base class or on the ActivityExecutionContext. Then you are in control of when that data gets sent to the tracking infrastructure, but your profile still determines if your service will receive the data at runtime.

Andreas wrote re: How to get workflow data/properties at runtime
on 11-17-2008 1:59 AM

Thanks Matt! You pointed me at the right direction and now I have a nice Tracking Service up 'n' running that monitors the specified events.

My next mission is to store the data in a sql. I hope this isn't as tricky as my former problems...

Add a Comment

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