I have come across problem in versioning of long running persisted workflows. Since persisted workflow is bound to the exact type in the assembly. That means changing an assembly with a newer version can create problem with the persisted workflow when we want to rehydrate it and stop working. So we need to maintain both versions of assembly and redirect the persisted workflows to older version of assembly. Assembly versioning can be maintained using assembly binding in web.config.
Steps for enabling side by side execution of workflow versions:
Create folder named with the same name as version of workflow say “1.0.0.1”.
Now copy the dll (version 1.0.0.1) into this folder.
Now copy this code into configuration section of web.config file.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="myWorkflow" publicKeyToken ="beba2b205e3be4cf"/>
<codeBase version="1.0.0.1" href="Bin/Ver1.0.0.1/ myWorkflow.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Change the assembly name, publicKeyToken and version according to yours assembly. You can get publicKeyToken by using command sn –tp “<assemlypath>” on a visual studio command prompt.
With this code we can redirect ver1 workflow to ver1 assembly.
Now problem arieses with ExternalDataExchange Services as we need to get instance of same version EDS service in which workflow was created and persisted. So for that we need to use late binding and create instance EDS service at runtime depending on the workflow version and then invoke the service. For this I have used reflection method.
public string ExecuteService(WorkflowRuntime workflowRuntime,string strWorkflowId)
{
// Obtatin communication service from Workflow Runtime
eds = workflowRuntime.GetService<ExternalDataExchangeService>();
// Obtatin scheduler service from Workflow Runtime ManualWorkflowSchedulerService schService = workflowRuntime.GetService<ManualWorkflowSchedulerService>();
Guid workflowId = new Guid(strWorkflowId);
// Get workflow instance
WorkflowInstance workflowInstance = workflowRuntime.GetWorkflow(workflowId);
Assembly assembly = workflowInstance.GetWorkflowDefinition().GetType().Assembly;
Type type = assembly.GetType(typeof(myEventService).FullName);
object myService = eds.GetService(type);
// Obtain communication service
if (myService == null)
{
myService = Activator.CreateInstance(type);
eds.AddService(myService);
}
try
{
MethodInfo myMethod = type.GetMethod("myEvent");
myMethod.Invoke(myService, new object[] {workflowInstance.InstanceId });
}
catch (Exception ex){}
schService.RunWorkflow(workflowInstance.InstanceId);
}
With this much code we are able to maintain versions of workflow. Enjoy creating multiple versions of workflow.