There are currently a couple of options to expose a Windows Workflow as as service.
I'm going to focus on Ad 1 and Ad 2 in this post.
Ad 1:
There's an option to host your workflow library inside a web service by using a "Publish as a Web Service" option inside Visual Studio 2005. This creates a separate ASP .NET Web Service project inside your current solution, which you can later manually or automatically publish as a web site to your IIS of choice.
The are two major downsides to this story. The first is that this gives you practically no control over how the web service is created. Second downside, while documented, is that the current implementation of System.Workflow.Runtime.WorkflowWebHostingModule works in particular ways with the workflow persistence story.
Let's assume we have to following interface defined for this web service:
interface IServiceInterface{ void SendOrder(Order order); Order GetOrder(Guid guidOrder); int GetOrderStatus(Guid guidOrder);}
What happens is (request number 1):
All good, right?
Actually, what happens during request number 2?
And all this is actually the expected behavior if you think hard enough. Workaround? Hit the endpoint with a newly loaded IE window. It works every time, since a cookie with an instance ID is not present.
Another thing to mention here is that this issue does not manifest itself if you hit the endpoint programatically using the web service proxy, unless you are using a CookieContainer class to cache the returning cookies.
Ad 2:
Hosting a Windows Workflow manually is another option, which gives you more flexibility towards the service detail tweeking.
You can host it using the following code:
[WebService(Namespace = "http://webservices.gama-system.com/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]public class WorkflowService : System.Web.Services.WebService{ // workflow runtime private static WorkflowRuntime workflowRuntime = new WorkflowRuntime(); [WebMethod] public void SendOrder(Order order) { AutoResetEvent waitHandle = new AutoResetEvent(false); workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); }; workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { waitHandle.Set(); };
// create workflow instance with the specified parameters WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(MyWorkflow)); instance.Start();
waitHandle.WaitOne(); } }
An important thing in the specified sample is that the System.Workflow.Runtime.WorkflowRuntime instance is static to the service implementation class. This is a requirement, since the workflow runtime can only get loaded once per appdomain. If this is not the case you will get an exception during the second invocation of the workflow.
If you are using any additional workflow runtime services, like persistence, tracking or your own communication service to communicate with the workflow you will need to track that the services get loaded once only. Here's the example:
[WebService(Namespace = "http://webservices.gama-system.com/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]public class WorkflowService : System.Web.Services.WebService{ // workflow runtime private static WorkflowRuntime workflowRuntime = new WorkflowRuntime(); // services added private static bool booServicesAdded = false;
// communication service private static CommunicationService objComm = new CommunicationService(); [WebMethod] public void SendOrder(Order order) { // add communication service if (!booServicesAdded) { ExternalDataExchangeService externalService = new ExternalDataExchangeService(); workflowRuntime.AddService(externalService); externalService.AddService(objComm); booServiceAdded = true; } AutoResetEvent waitHandle = new AutoResetEvent(false); workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); }; workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { waitHandle.Set(); };
This adds the required services only during the first invocation of a web service. Since workflow runtime is a static class the services get persisted during all subsequent service calls. A boolean variable booServicesAdded is responsible for flag storage.
Remember Me
The opinions expressed herein are my own personal opinions and do not represent my company's view in any way.
My views often change.
This blog is just a collection of bytes.
Copyright © 2003-2024Matevž Gačnik
E-mail