September 2008 - Posts
Part 1
Part 2
Part 3
Part 4
In the previous blog posts we made sure we could have multiple versions of the same workflow running side by side. This ability is one of the more powerful concepts of WF and a real must have for long running business applications.
A quick recap.
Always version your assemblies by giving them a strong name. Make sure the runtime can find each version of the assembly by pointing the CLR to the right version using the configuration\runtimeassemblyBinding\dependentAssembly\assemblyIdentity\codeBase in your App.Config (or Web.Config in the case of a web application). And make sure you use all types and interfaces from the same version as the workflow or, somewhat easier, stick to using basic CLR types when sending messages.
Great, but what about fixing bugs?
All the versioning is very nice but the simple fact is that sooner or later you are going to find a bug in your code and need to fix a specific assembly. In that case it would not be very nice if the workflow would keep on running with the buggy code. No in that case you would very much like to be able to dehydrate the worfklows and have them use the patched version of the assembly instead of the original one.
Fortunately this is easy to do, and again due to the standard binary serialization format Windows Workflow Foundation uses, completely standard .NET.
Again the trick is versioning the assembly and using the App.Config to redirect the runtime to the correct version. So just as I demonstrated in the previous posts I need to strongly sign the assembly. Next when we want to fix a bug in the assembly we need to update the version number and redirect the CLR to the new version. The last part is done using the following config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WorkflowLibrary1" publicKeyToken="8afb6d596a769080" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="1.0.1.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
To demonstrate the effect the workflow below is started with a parameter that indicates the assembly version it was when started and prints this, long with the current assembly version, on the screen. as you can see the first workflow was started with version 1.0.0.0 but the assembly actually executing is updated to 1.0.1.0. In contrast the second workflow was created using the assembly 1.0.1.0.
So why bother to update the version number in the first place?
After all you could just leave the version number as is and replace the assembly. The main disadvantage is that it makes it harder to see which version was executing when a new bug report comes in. Was this the patched assembly and is the bug still there under specific circumstances? On other words: was the bug fix buggy
. Or is the system still using the original assembly, and was the update not done correctly? Best just to avoid these kind of problems and make sure you can see which version either by looking at the assembly file properties or by having an error handler print all loaded assemblies, including version number.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Part 1part 2Part 3Part 4 You may recall my previous posts about using the TransactionScopeActivity within a ReceiveActivity and all the nasty issues we ran into. Just in case you want to read them again: one, two and three.
As it turn out this is an intentionally not supported scenario at the moment. If we read the docs for the ReceiveActivity we can find the following note:
To ensure that persistence performs properly and does not persist transient messages, make sure that child activities of the ReceiveActivity do not persist by themselves. This can occur if the child activities go idle when a persistence provider was created with UnloadOnIdle set to true, for instance.
The note uses the UnloadOnIdle as an example but the persistence part is just as much true for the TransactionScopeActivity as this persists the state. Of course there is no similar warning in the TransactionScopeActivity docs
and the activity validation fails to warn us either so there is definitely some room for improvement here.
But rumor has it that this improvement is coming
The rumor says that not only will we be able use a TransactionScopeActivity inside of a ReceiveActivity but we can even go a step further in being able to flow a transaction from the client through the WCF request into the workflow and have the TransactionScopeActivity participate in the same transaction. Nice but I guess we will have to wait for the PDC before we get all the details.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Part 1 Part 2 Part 3 Part 4 In the first article of this series I demonstrated how to get multiple versions of a workflow running side by side in the same workflow runtime. The most important thing was that you need to keep every version of the assembly around and use the assemblyBinding element in the app.config to let the runtime know where each version was on disk. Once done life was good 
In the second part I demonstrated how a HandleExternalEventActivity was version dependent and you needed to use the version specific service to send a message to the workflow. It worked but the as the code was not exactly pretty life was just ok
.
What is wrong with the HandleExternalEventActivity?
Well there is nothing really wrong with the HandleExternalEventActivity but it is a very thin layer over the actual workflow structures it tries to hide. And these structures are the workflow queuing mechanism! Internally everything is turned into a message and send through a queue. So if this is only a thin abstraction layer why not use the original API in the first place.
That is exactly what I advise, leave the external data exchange mechanism for what it is and just create a custom workflow activity.
What does it take to implement the same behavior using a custom activity? Not a whole lot actually so lets take a look.
Above is the new workflow with the custom activity.
Because the custom activity is used as the first child in one of the branches of a ListenActivity it must implement the IEventActivity interface and we must override the Execute method to do something once a message is found in the queue.
using System;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
namespace WorkflowLibrary1
{
public partial class MyActivity : Activity, IEventActivity
{
public static string TheQueueName = "MyActivityQueueName";
protected override ActivityExecutionStatus Execute(
ActivityExecutionContext executionContext)
{
WorkflowQueuingService wqs = executionContext.GetService<WorkflowQueuingService>();
WorkflowQueue queue = wqs.GetWorkflowQueue(QueueName);
object data = queue.Dequeue();
Console.WriteLine("Received {0} in {1}", data, GetType().Assembly.FullName);
return base.Execute(executionContext);
}
public IComparable QueueName
{
get { return TheQueueName; }
}
public void Subscribe(
ActivityExecutionContext parentContext,
IActivityEventListener<QueueEventArgs> parentEventHandler)
{
WorkflowQueuingService wqs = parentContext.GetService<WorkflowQueuingService>();
WorkflowQueue queue = null;
if (wqs.Exists(TheQueueName))
queue = wqs.GetWorkflowQueue(TheQueueName);
else
queue = wqs.CreateWorkflowQueue(QueueName, true);
queue.RegisterForQueueItemAvailable(parentEventHandler);
}
public void Unsubscribe(
ActivityExecutionContext parentContext,
IActivityEventListener<QueueEventArgs> parentEventHandler)
{
WorkflowQueuingService wqs = parentContext.GetService<WorkflowQueuingService>();
WorkflowQueue queue = wqs.GetWorkflowQueue(TheQueueName);
queue.UnregisterForQueueItemAvailable(parentEventHandler);
}
}
}
I am not going to explain the details except that the message is read in the Execute and is printed as is along with the assembly version. And guess what, If I create multiple versions of the workflow and run them side by side life is good
.
Sending the data was easy too with only the following code:
static void SendEvent1(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
instance.EnqueueItem(MyActivity.TheQueueName, 1, null, null);
}
However the data send in this simple example is only an integer. Lets see what happens when we use a custom object instead of the single integer.
The case of the custom message type
In the previous example everything worked just fine because we only send in a real simple data type, an integer. However when we switch to a custom type things are less perfect
.
For this example I am using the following data type:
namespace WorkflowLibrary1
{
public class MyData
{
public MyData(int data)
{
TheData = data;
}
public int TheData { get; set; }
public override string ToString()
{
return string.Format("Data = {0}", TheData);
}
}
}
Still real simple but non the less a custom type we can version along with the workflow and its activities. The code to send the message becomes as follows:
static void SendEvent1(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
MyData data = new MyData(1);
instance.EnqueueItem(MyActivity.TheQueueName, data, null, null);
}
Again not a spectacular change as we only substitute the integer for an object of type MyData. The activity execute changes to the following:
protected override ActivityExecutionStatus Execute(
ActivityExecutionContext executionContext)
{
WorkflowQueuingService wqs = executionContext.GetService<WorkflowQueuingService>();
WorkflowQueue queue = wqs.GetWorkflowQueue(QueueName);
MyData data = (MyData)queue.Dequeue();
Console.WriteLine("Received {0} in {1}", data, GetType().Assembly.FullName);
return base.Execute(executionContext);
}
Again no big change, all we are doing is casting the data from the queue to be of type MyData. When we run this with a workflow started using the latest version everything is just fine but when I send a message to a workflow version 1.0.0.0 we receive the following InvalidCastException message:
Unable to cast object of type 'WorkflowLibrary1.MyData' to type 'WorkflowLibrary1.MyData'
That message seems kind of weird as it is claiming that we cannot cast MyData to MyData!. Weird as this may seem it is completely true!
The problem, and things would have been clearer of the message include this information is that we cannot cast between two different versions of the same type as they are really different types.
The solution
Just like the previous time the solution is to create an object of the same type as was used in the custom workflow activity. The concept is pretty much the same as last time with the ExternalDataExchangeService and requires a bit of reflection.
static void SendEvent2(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
Assembly assembly = instance.GetWorkflowDefinition().GetType().Assembly;
Type type = assembly.GetType(typeof(MyData).FullName);
object data =Activator.CreateInstance(type, new object[] {1});
instance.EnqueueItem(MyActivity.TheQueueName, data, null, null);
}
using this code both the workflow and the runtime are perfectly happy. That said, personally I don't really like having to resort to reflection every time
So instead of using typed objects you might just want to resort to using basic framework objects which will remain the same version until a major .NET framework upgrade. One easy way to send data is just embed it in an XML document or, just as the workflow parameters, a Dictionary<string, object> and pass that along.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Part 1 Part 2 Part 3 Part 4 In my previous post I demonstrated how to keep multiple versions of an assembly around and how to use the assemblyBinding element in the app.config to let the runtime load multiple versions of a worklfow. In the end we had both workflows, the first in assembly 1.0.0.0 and the second in assembly 2.0.0.0, running and life seemed to be good 
So is there more to write on the subject? Yes unfortunately there are still some potential problems that need to be addressed
.
The pitfalls of External Data Exchange
Lets take a look at what happens if we add a HandleExternalEventActivity to the mix. This HandleExternalEventActivity can be used to have a workflow react to input from an external data exchange service, sometimes called local communication.
Lets change the workflow to reflect the following:
In this workflow I am waiting for either a DelayActivity to fire or an event to be raised from an external service. Like before the activities are emended in a permanent loop so the workflow is never finished.
I have kept the external data exchange service real simple. The interface looks like this:
using System;
using System.Workflow.Activities;
namespace WorkflowLibrary1
{
[ExternalDataExchange]
public interface IMyService
{
event EventHandler<MyEventArgs> TheEvent;
}
}
The implementation like this:
using System;
namespace WorkflowLibrary1
{
public class MyService : IMyService
{
public event EventHandler<MyEventArgs> TheEvent;
public void OnTheEvent(Guid instanceId)
{
if (TheEvent != null && instanceId != Guid.Empty)
{
MyEventArgs args = new MyEventArgs(instanceId, DateTime.Now);
TheEvent(null, args);
}
}
}
}
And the event parameter looks like this:
using System;
using System.Workflow.Activities;
namespace WorkflowLibrary1
{
[Serializable]
public class MyEventArgs : ExternalDataEventArgs
{
public DateTime FiredAt { get; set; }
public MyEventArgs(Guid instanceId, DateTime firedAt)
: base(instanceId)
{
FiredAt = firedAt;
}
}
}
Not much complexity there
.
In the main function the workflow runtime is created and configured again. This time we also need to add the MyService as follows:
ExternalDataExchangeService edes = new ExternalDataExchangeService();
workflowRuntime.AddService(edes);
MyService myService = new MyService();
edes.AddService(myService);
The complete main function is at the bottom of the post but the most important things are the two Guids. The variable instanceId1 holds the WorkflowInstanceId from a workflow version 1.0.0.0 while the variable instanceId2 holds a WorkflowInstanceId from a workflow version 2.0.0.0. Both of these have been created during two previous runs and are saved by the SqlWorkflowPersistenceService added to the runtime. So lets see what happens when I run the application.

As we can see from the screenshot both workflows, the first in assembly 1.0.0.0 and the second in assembly 2.0.0.0, are running together just fine. So lets see what happens when we raise the event TheEvent as declared in the external data exchange interface.
As we can see from the screenshot above the second version of the workflow receives the event just fine but version 1.0.0.0 doesn't and instead we receive the following exception:
Event "TheEvent" on interface type "WorkflowLibrary1.IMyService" for instance id "c9592a1b-e703-4726-b9bb-16410a7aaaad" cannot be delivered.
Now the workflow did manage to receive the event when it was just created, in fact it could up until the moment we recompiled the application and deployed version 2.0.0.0. Neither the workflow nor the service has changed so what gives?
Underneath the covers of the HandleExternalEventActivity
To understand the problem we must first understand a bit more about the internals of the HandleExternalEventActivity. When we created the ExternalDataExchange interface we declared an event taking a parameter derived from ExternalDataEventArgs. And when configuring the HandleExternalEventActivity we specified an event name so everything works using .NET events right? Well no, wrong!
In fact pretty much everything in Windows Workflow Foundation works based on queues. In fact due to the long running nature and the fact you don't really know when thing will execute it must do so. In fact that is the reason why the event parameter must be marked with the Serializable attribute. In fact the ExternalDataExchangeService watches every for every possible event and converts every event into a queued message.
Okay nice to know but how does that help with this problem?
Well the thing is it needs to be able to find the correct queue to send the message and that is where things get interesting. When we look at WF queues we see that queue names are of type IComparable. Now most of the time when creating a queue the easiest thing to do is use a string or a guid as the queue name. And as both implement IComparable this is perfectly legal. But in the case of the ExternalDataExchangeService and the HandleExternalEventActivity both need to be able to construct the same queue name based upon the interface and event name. And this is where the EventQueueName enters.
The EventQueueName also implements IComparable and is used internally to uniquely identify a queue name. And when the EventQueueName checks if two queues are the same it doesn't just use the interface name and the event name but it also compares the assemblies both are defined in. So in this case the workflow version 1.0.0.0 is creating a queue that contains the fact that it is from version 1.0.0.0 as part of the contract while the runtime only uses the last version this creating a queue that contains version 2.0.0.0 as part of the queue name.
We can use the following code to pint the queue information from each workflow:
static void PrintQueues(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
ReadOnlyCollection<WorkflowQueueInfo> queues = instance.GetWorkflowQueueData();
foreach (var queue in queues)
{
EventQueueName queueName = queue.QueueName as EventQueueName;
if (queueName != null)
{
Assembly assembly = queueName.InterfaceType.Assembly;
Console.WriteLine(queueName);
Console.WriteLine(queueName.InterfaceType.Assembly.FullName);
Console.WriteLine();
}
}
}
With this as the result:

The solution
The original function used raise the event looked like this:
static void SendEvent1(WorkflowRuntime workflowRuntime, Guid instanceId)
{
MyService myService = workflowRuntime.GetService<MyService>();
myService.OnTheEvent(instanceId);
}
The reason this is failing should now be apparent. After all the main program binds to the version of WorkflowLibrary1 it was build against or version 2.0.0.0. So the GetService() call returns a service object that created a queue name containing version 2.0.0.0 as part of its name and cannot call a HandleExternalEventActivity that creates a queue version 1.0.0.0.
So the solution is to create the correct service object. Doing so isn't complicated but does unfortunately requires some reflection because we need to work with the same type from an older assembly.
static void SendEvent2(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
Assembly assembly = instance.GetWorkflowDefinition().GetType().Assembly;
ExternalDataExchangeService edes = workflowRuntime.GetService<ExternalDataExchangeService>();
Type type = assembly.GetType(typeof(MyService).FullName);
object myService = edes.GetService(type);
if (myService == null)
{
myService = Activator.CreateInstance(type);
edes.AddService(myService);
}
MethodInfo mi = type.GetMethod("OnTheEvent");
mi.Invoke(myService, new object[] { instanceId });
}
This code first gets an assembly reference to the assembly the actual workflow was defines in. Depending on the workflow this is either going to return assembly version 1.0.0.0 or version 2.0.0.0. Once we have this reference we retrieve the correct service type from the assembly. This type is different for each assembly so when we ask the ExternalDataExchangeService for the service it will try to return one with the correct type information. If this isn't found yet it will return null and we can use the Activator.CreateInstance() to create the correct type adding it to the ExternalDataExchangeService for next time.
Next we use reflection to execute the OnTheEvent we defined to fire the event for the workflow which now uses the correct version information when creating the queue name and everything works just fine.
The screenshot above shows that both workflow versions are able to receive events again.
Conclusion
The code above works and solves the problem but is not very nice. It assumes that the ExternalDataExchange is defined in the same assembly as the workflow, something that doesn't need to be the case. So is there a better solution? Yes but that is the subject of another blog post.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
The complete main program:
using System;
using System.Workflow.Activities;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using WorkflowLibrary1;
using System.Reflection;
using System.Collections.ObjectModel;
namespace WorkflowConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
ExternalDataExchangeService edes = new ExternalDataExchangeService();
workflowRuntime.AddService(edes);
MyService myService = new MyService();
edes.AddService(myService);
string connStr = @"Data Source=.\sqlexpress;Initial Catalog=WorkflowPersistence;Integrated Security=True";
SqlWorkflowPersistenceService persistence = new SqlWorkflowPersistenceService(connStr,
true, TimeSpan.FromSeconds(15), TimeSpan.FromMinutes(1));
workflowRuntime.AddService(persistence);
workflowRuntime.ServicesExceptionNotHandled += (sender, e) =>
{
Console.WriteLine(e.Exception.Message);
};
workflowRuntime.StartRuntime();
Guid instanceId1 = new Guid("c9592a1b-e703-4726-b9bb-16410a7aaaad");
Guid instanceId2 = new Guid("482e2742-e7c7-45e2-bcd3-8f894d200733");
//WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(Workflow1));
//instanceId2 = instance.InstanceId;
//instance.Start();
bool done = false;
while (!done)
{
try
{
ConsoleKeyInfo key = Console.ReadKey(true);
switch (key.KeyChar)
{
case '1':
SendEvent2(workflowRuntime, instanceId1);
break;
case '2':
SendEvent2(workflowRuntime, instanceId2);
break;
case '5':
PrintQueues(workflowRuntime, instanceId1);
break;
case '6':
PrintQueues(workflowRuntime, instanceId2);
break;
case '0':
done = true;
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
workflowRuntime.StopRuntime();
}
}
static void SendEvent1(WorkflowRuntime workflowRuntime, Guid instanceId)
{
MyService myService = workflowRuntime.GetService<MyService>();
myService.OnTheEvent(instanceId);
}
static void SendEvent2(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
Assembly assembly = instance.GetWorkflowDefinition().GetType().Assembly;
ExternalDataExchangeService edes = workflowRuntime.GetService<ExternalDataExchangeService>();
Type type = assembly.GetType(typeof(MyService).FullName);
object myService = edes.GetService(type);
if (myService == null)
{
myService = Activator.CreateInstance(type);
edes.AddService(myService);
}
MethodInfo mi = type.GetMethod("OnTheEvent");
mi.Invoke(myService, new object[] { instanceId });
}
static void PrintQueues(WorkflowRuntime workflowRuntime, Guid instanceId)
{
WorkflowInstance instance = workflowRuntime.GetWorkflow(instanceId);
ReadOnlyCollection<WorkflowQueueInfo> queues = instance.GetWorkflowQueueData();
foreach (var queue in queues)
{
EventQueueName queueName = queue.QueueName as EventQueueName;
if (queueName != null)
{
Assembly assembly = queueName.InterfaceType.Assembly;
Console.WriteLine(queueName);
Console.WriteLine(queueName.InterfaceType.Assembly.FullName);
Console.WriteLine();
}
}
}
}
}
Part 1 Part 2 Part 3 Part 4
One of the cool features of Windows Workflow Foundation is that it allows long running processes. And not just long running as in a few minutes but really long running as in a few years
. This is possible true the use of the SqlWorkflowPersistenceService, or in fact any derived class from WorkflowPersistenceService, which is going to save the state of a workflow to disk when it is not actually busy.
So that is pretty cool but it is kind of unlikely that your programs are not going to change over a year so in all likelihood you are going to be deploying newer versions of your assemblies while there are multiple workflow's active. In order to allow multiple versions of a workflow to run we need to understand what is going on under the covers.
To demonstrate the behavior I am going to use a small project with the following layout. The WorkflowConsoleApplication1 is the host and is configured to use SqlWorkflowPersistenceService. The WorkflowLibrary1 is the project containing the actual workflow and this is the project we are going to version.
The main program is pretty simple and looks like this:
static void Main(string[] args)
{
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
string connStr = @"Data Source=.\sqlexpress;Initial Catalog=WorkflowPersistence;Integrated Security=True";
SqlWorkflowPersistenceService persistence = new SqlWorkflowPersistenceService(connStr,
true, TimeSpan.FromSeconds(15), TimeSpan.FromMinutes(1));
workflowRuntime.AddService(persistence);
workflowRuntime.ServicesExceptionNotHandled += (sender, e) =>
{
Console.WriteLine(e.Exception.Message);
};
workflowRuntime.StartRuntime();
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(Workflow1));
instance.Start();
Console.WriteLine("Press ennter to stop");
Console.ReadLine();
workflowRuntime.StopRuntime();
}
}
Basically it sets up the SqlWorkflowPersistenceService, starts the runtime, starts a new workflow and waits for the user to terminate the program. It also prints any exceptions that might occur in a workflow runtime service like the SqlWorkflowPersistenceService.
The workflow is real simple. It just loops forever and prints a message that includes the assembly version number every 10 seconds.
What we are going to do is start this program so we have a first instance in the persistence store, update the workflow assembly to version two an have version 1 and 2 run side by side.
The WorkflowPersistenceService part.
The WorkflowPersistenceService actually persists, or dehydrates as it is called, a workflow using the binary serializer. This means that when it recreates, or dehydrates as this is called, the workflow instance it is done in a assembly version depended manner. So the first thing to be aware of is the standard .NET versioning behavior.
For a .NET assembly to be versionable the first prerequisite is that it has a string name. The rules are simple, no strong name = no versioning and the first assembly found will be the one that is used. Now there is a potential problem here because the binary serializer uses the most compact form possible and doesn't store field names, only their value. The object is responsible for reading the data from a stream in the correct order and size. No problem as long as the same type that was serialized is actually used to deserialize an object. But suppose a newer type is used that actually expects extra fields? Well it is going to try to read some data that is not actually there and the process is going to fail
.
Versioning assemblies is important!
So in order to be able to version the WorkflowLibrary1 assembly we need to add a strong name. This is done in the project settings on the Signing tab as follows:
When we run the application we can see from the following output that the workflow version 1 is running just fine
.
Once we have stopped the application its time to upgrade to version 2.0.0.0. Now I am not even going to make any changes to the workflow, all I am going to do is change the assembly major version number of the WorkflowLibrary1 project to 2. This is actually stored as part of the assembly and thus causes the project to recompile.
If we run the application again we are going to see the following output:
While version 2.0.0.0 of the workflow will run just fine version 1.0.0.0 cannot be loaded and the SqlWorkflowPersistenceService reports the following error via the WorkflowRuntime ServicesExceptionNotHandled event.
Could not load file or assembly 'WorkflowLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8afb6d596a769080' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
This error is the result of the binary serializer seeing that the workflow was dehydrated with version 1.0.0.0 of the WorkflowLibrary1 so it wants to load that version. And that is nowhere to be found as we only have version 2.0.0.0 which is not good enough.
Enabling side by side execution
The first ting we need to do is make sure we have both versions of the assembly WorkflowLibrary1 available. In order to do so we need to create a folder in the bin\Debug folder with the name Version_1_0_0_0. This is the folder where I am going to keep a copy of the WorkflowLibrary1.dll version 1.0.0.0.
Next we need to tell the .NET runtime where to look for version 1.0.0.0 of the assembly by adding this information to the app.config of our application. This is standard .NET material and in no way specific to Windows Workflow Foundation. The app.config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WorkflowLibrary1" publicKeyToken="8afb6d596a769080" />
<codeBase version="1.0.0.0" href="Version_1_0_0_0/WorkflowLibrary1.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
With both versions of the assembly and configuring the runtime so it knows where to find the first version of the assembly both versions of the workflow will run happily together
.
So how about the GAC?
In this example I use a private location to store multiple versions of the assembly but I could also have used the Global Assembly Cache, of GAC for short, to do this. Both mechanisms allow an assembly to be versioned so which is better? Normally the GAC should be used by assemblies used with multiple applications. In this case, and this is probably the case with most workflow assemblies, the WorkflowLibrary1 assembly only used by our host and not by other applications making a private location the proper place. That said there are certainly scenarios, like shared custom activity assemblies, where the GAC would be the proper place.
So are we all set?
No unfortunately not quite because there are some more issues that might crop up with versioning. So stay tuned for more 
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
One powerful feature of a workflow is that a workflow can be changed at runtime. Like other powerful features this is something that should be done with care but it can be a real life saver at times.
One of the things that you can change are Declarative Rule Conditions. However as these rules are really CodeDom objects it can be a bit tricky to find the right property to change. However once you know a little tick life is much easier.
The trick is in the .rules file created when you add a Declarative Rule Condition to the workflow and is best demonstrated using a small example. Take the following workflow:
The IfElseActivity has a Declarative Rule Condition which looks like this:
So I consider every amount larger that 100 large. Hmm not much, lets change that to 1000 instead of 100 
The first step is we need to change the workflow instance so we need a WorkflowChanges object passing in the workflow root as the activity. No big deal but what now. Well lets open the Workflow1.Rules file and take a look at what is inside.
<RuleDefinitions xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<RuleDefinitions.Conditions>
<RuleExpressionCondition Name="LargeAmountRule">
<RuleExpressionCondition.Expression>
<ns0:CodeBinaryOperatorExpression Operator="GreaterThan" xmlns:ns0="clr-namespace:System.CodeDom;Assembly=System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<ns0:CodeBinaryOperatorExpression.Left>
<ns0:CodePropertyReferenceExpression PropertyName="Amount">
<ns0:CodePropertyReferenceExpression.TargetObject>
<ns0:CodeThisReferenceExpression />
</ns0:CodePropertyReferenceExpression.TargetObject>
</ns0:CodePropertyReferenceExpression>
</ns0:CodeBinaryOperatorExpression.Left>
<ns0:CodeBinaryOperatorExpression.Right>
<ns0:CodePrimitiveExpression>
<ns0:CodePrimitiveExpression.Value>
<ns1:Int32 xmlns:ns1="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">100</ns1:Int32>
</ns0:CodePrimitiveExpression.Value>
</ns0:CodePrimitiveExpression>
</ns0:CodeBinaryOperatorExpression.Right>
</ns0:CodeBinaryOperatorExpression>
</RuleExpressionCondition.Expression>
</RuleExpressionCondition>
</RuleDefinitions.Conditions>
</RuleDefinitions>
It turns out that the XML is a very literal representation of the objects that make up our rule and what we need to change. So we need to start with a RuleDefinitions.
RuleDefinitions rules =
(RuleDefinitions)changes.TransientWorkflow.GetValue(RuleDefinitions.RuleDefinitionsProperty);
So getting our hand on it is easy, just use the GetValue function passing in the RuleDefinitionsProperty dependency property.
Once we have this things are even easier as it is just following the XML
. It shows the RuleDefinitions object has a Conditions property and our rule is in there with a name LargeAmountRule and is of type RuleExpressionCondition. This rule in turn contains a left and right part with the right part pointing at the value of 100 we want to change. Again this value is of a type CodePrimitiveExpression, another easy cast. The code below is the complete code required to change the value from 100 to1000.
WorkflowChanges changes = new WorkflowChanges(this);
RuleDefinitions rules =
(RuleDefinitions)changes.TransientWorkflow.GetValue(RuleDefinitions.RuleDefinitionsProperty);
RuleExpressionCondition rule = (RuleExpressionCondition)rules.Conditions
.First(rc => rc.Name == "LargeAmountRule");
CodeBinaryOperatorExpression expression = (CodeBinaryOperatorExpression)rule.Expression;
CodePrimitiveExpression primitive = (CodePrimitiveExpression)expression.Right;
primitive.Value = 1000;
ApplyWorkflowChanges(changes);
Easy once you know where to look 
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu