I have seen this topic come up again and again, even outside these forums, so I wanted to share my experience and hopefully get some input from the experts.
So the scenario is that we'd like to store workflows as XAML files inside a database, and later on call into a central WF service with a key that identifies a particular file, and start an instance of that deserialized workflow. Of course, this being an enterprise application, we'd like persistence/scalability/managability, so having the central WF service hosted in an AppFabric environment would be ideal.
After many, many hours of experimenting, we've discovered that the contrived examples of ActivityXamlServices are useless since they all ultimately end up calling WorkflowInvoker, which doesn't support persistence. We've tried using NativeActivity because we wanted child workflows to continue using the same context as the parent workflows (making tracking easier since all child workflows would be tracked under the same WorkflowInstanceID as the parent), and since scheduling provides that mechanism, and NativeActivity is the only activity that allows for scheduling. Here we discovered the chicken-and-egg problem of Workflow: you cannot "alter" a workflow's definition after it has begun executing because the entire workflow tree is built before it begins to execute; since dynamically loading a workflow and then scheduling its root activity for execution by the parent NativeActivity is, in effect, altering the workflow to which the NativeActivity belongs, you would have to define (within NativeActivity's CacheMetadata method) all possible custom workflows the NativeActivity might need to schedule, then pick the appropriate one during the Execute block. This technique would be fine if there were only a handful of possible custom activities, but is unscalable when there could be hundreds or thousands.
Ditto for DynamicActivity, since its Implementation delegate is called before the Execute method, and the Execute method is the first opportunity to get at the XAML file key needed to load the appropriate file.
So the solution we've come up with is to create a method that loads the XAML file from the database, turning it into an activity using ActivityXamlServices as before, and use it to create a WorkflowServiceHost (thus making it compatible with the facilities provided by AppFabric); we invoke this method from a central "dispatcher" XAMLX service when we need to start an endpoint, and call the endpoint with a Send activity whose endpoint address is changed to match the new endpoint's. It appears that since the dispatcher service endpoint is in the same domain as the dynamically-created endpoints, the workflow "flows" its WorkflowInstanceID into the new endpoint, and our tracking problem is solved. We just have to make sure that any running dynamic endpoints are restarted when the host application domain is restarted. While we're testing this approach, our solution is to simply start all dozen or so test workflow endpoints in global.asax during ApplicationStart; longer-term, we're going to have to have a more sophisticated approach.
Does anyone have anything to add from their own experience?
10 февраля 2011 г. 23:30
- Перемещено Andrew_Zhu 14 февраля 2011 г. 6:08 (From:.NET 4: Windows Workflow Foundation)
Have you looked into using a VirtualPathProvider? It allows you to intercept the request and provide the right xamlx file for it.
AFAIK it can only key off the path portion of the URL, so if you want to key off the message body, you could use the WCF Routing Service to intercept the message and route it to the correct "virtual path" which would then be resolved from your database.11 февраля 2011 г. 6:26
Do u've a sample code of the dispatcher xamlx service?
Or even the more sophisticated approach?
I've the same idea that it isn't easy to host xaml while keeping all the AppFabric features.
Ron Jacobs posted an sample program which uses a database to store xamlx service workflows.
But still it is only for xamlx and not for xaml
http://code.msdn.microsoft.com/Windows-Workflow-8697594e20 июля 2011 г. 8:22
- Have a look at my article WorkflowChannel for Routing Service. The following picture shows this concept:
This concept can also be used on Windows Azure, see my recent article RoutingService on Azure, where a Runtime Repository for storing a xaml activities is used an Azure Storage Blob Container.
Roman Kiss, MVP Connected System Developer1 августа 2011 г. 19:54
Do you have a sample of the code that you could share about the functionality you achieved. I have a similar problem to deal with, where I have bunch of XAML files in the repository and I would like to load them and execute the workflows, but utilize the AppFabric features with it.14 июля 2012 г. 15:20