Managing workflows with WorkflowControlClient
How the heck does it work?! MSDN is surprisingly unhelpful on this matter (list of class members with couple of very obvious one-line snippets is a mockery of documentation).
Unfortunately, when configuring the IWorkflowInstanceManagement interface you have to be very precise. Let’s do it step by step, and while we are at that, let’s make the service implementation more WCF-compliant.
1. Make your workflow service implement a contract. There won’t be a magic but rather a trick – the workflow service will think that it exposes an interface, name of which you typed in the ServiceContractName of your Receive shapes after {http://tempuri.org} (if you didn’t – do it) and it accidentally matches the interface with the same name in your code (or something similar to that).
In our case let’s name the XAML interface {http://TeddyBearStore.com/Contracts/}ITeddyBearService and our “artificial interface” - TeddyBearStore.Contracts.ITeddyBearService
2. Make WF service look like good old WCF. By default WF service, hosted in IIS is exposed as a magic no-name service: service tag is completely missing and only nameless ServiceBehavior allows some primitive configuration.
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true"/> <!--<sqlWorkflowInstanceStore connectionStringName="WF4Persistence" />--> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
You can make it more WCF-like by adding a real service in the configuration file and naming the behavior:
<services> <service name="TeddyBearService" behaviorConfiguration="workflowServiceBehavior"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" contract="ITeddyBearService" /> </service> </services>
Very, very important for the Workflow Control Client – the service name must match exactly the ConfigurationName property (can be found at the top of the XAML file or in the Properties window in the workflow designer window).
3. Add the Workflow Control Endpoint:
<services> <service name="TeddyBearService" behaviorConfiguration="workflowServiceBehavior"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" contract="ITeddyBearService" /> <endpoint address="wce" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" kind="workflowControlEndpoint" /> </service> </services>
4. Add standard endpoint description. They might be accessible by default but I did not bother to test this assumption, so add them in the web.config anyway. This is your last step for the service side.
<services> <service name="TeddyBearService" behaviorConfiguration="workflowServiceBehavior"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" contract="ITeddyBearService" /> <endpoint address="wce" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" kind="workflowControlEndpoint" /> </service> </services> <standardEndpoints> <workflowControlEndpoint> <standardEndpoint/> </workflowControlEndpoint> </standardEndpoints>
5. Add client endpoints, one for your service (remember the “artificial” TeddyBearStore.Contracts.ITeddyBearService contract?) and another - for the Workflow Control Client functionality, which is essentially gives you an access to the AppFabricesque goodness. Note that the latter has /wce added to the address because the XAML service will refuse to expose both contracts from the same address.
<client> <endpoint name="TeddyBearEndpoint" address="http://localhost/TeddyBearStore/Services/TeddyBear.xamlx" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" contract="TeddyBearStore.Contracts.ITeddyBearService"/> <endpoint name="TeddyBearControlEndpoint" address="http://localhost/TeddyBearStore/Services/TeddyBear.xamlx/wce" binding="basicHttpBinding" bindingConfiguration="myBasicHttpBinding" contract="System.ServiceModel.Activities.IWorkflowInstanceManagement"/> </client>
6. Embrace the power. Now finally you have a fine-tuned control over you workflow services:
WorkflowControlClient client = new WorkflowControlClient("TeddyBearControlEndpoint"); client.Terminate(id);
Enjoy.
Special thanks to: Leon Woo, Funky Mule, Ron Jacobs
Thanks to: StackOverflow
No thanks to: MSDN
1 comment:
Thanks a lot for this great post. It really saved my day.
Post a Comment