So we’ve been on WF 4.0 for a while now, and we have been anxiously awaiting Dublin (AppFabric). One of the things we really wanted out of AppFabric was the ability to resume workflows that have suspended due to unhandled exceptions.
Well, I discovered that you don’t need AppFabric. The sql instance store already gives us that functionality…there’s just no GUI for it (that I can find).
So, start by creating the databases. The scripts are in the framework folder:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\SQL\en\SqlWorkflowInstanceStoreSchema.sql
C:\Windows\Microsoft.NET\Framework\v4.0.30319\SQL\en\SqlWorkflowInstanceStoreLogic.sql
Now, in the service behavior for the workflow xamlx, add some entries:
<sqlWorkflowInstanceStore connectionStringName="Workflow"
hostLockRenewalPeriod="00:00:05"
runnableInstancesDetectionPeriod="00:00:02"
instanceCompletionAction="DeleteAll"
instanceLockedExceptionAction="AggressiveRetry"
instanceEncodingOption="None" />
<workflowIdle timeToPersist="00:00:02"
timeToUnload="00:00:05"/>
Make sure your connection string name matches your connection string to the database tables you created from the above sql scripts.
One more configuration item to add. The workflow control endpoint needs to be added to the xamlx workflow service.
<service name="MyWorkflowService"
behaviorConfiguration="myServiceBehavior">
<endpoint address=""
binding="customBinding"
bindingConfiguration="myBindingConfiguration"
contract="IMyContract" />
<endpoint address="wce"
binding="basicHttpBinding"
kind="workflowControlEndpoint"/>
</service>
The endpoint with ‘kind=”workflowControlEndpoint”’ (new for .NET 4.0) is the key here. That creates the workflow control endpoint on your workflow service.
Now, after I get an exception in a workflow (and on my development machine, there has been many), the InstancesTable in the instance store contains the information we need. Running the sql:
select Id, SuspensionExceptionName, SuspensionReason, ExecutionStatus
from [System.Activities.DurableInstancing].InstancesTable
where IsSuspended = 1
I get these records:
So, here I can see the suspended workflows. What I need from here is the Id.
Now, let’s call the endpoint we created above. It’s a piece of cake:
You need a reference to System.ServiceModel.Activities v4. On my machine it’s found at C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Activities.dll. This assembly contains the classes WorkflowControlEndpoint and WorkflowControlClient.
Guid workflowId = SelectWorkflowIdSomehow();
WorkflowControlEndpoint ep = new WorkflowControlEndpoint(
new BasicHttpBinding(),
new EndpointAddress("http://localhost/myWorkflowService.xamlx/wce")
);
WorkflowControlClient client = new WorkflowControlClient(ep);
client.Unsuspend(workflowId);
That’s it. The WorkflowControlEndpoint does the work, and the workflow is unsuspended and resumed from the last persisted state before the exception happened. Essentially, everything that happened between un-persistence and the exception is gone, and the previous state is loaded.
Cool, huh? And you don’t even need AppFabric. AppFabric does add a nice layer of UI for persistence and tracking, so I’m still looking forward to it! :)
Enjoy. Or don’t. Whatever.
d7897ca6-d59e-4529-85b5-e3831cd08340|0|.0
Development
workflow | wcf