On the WF ReceiveActivity and WCF bindings
The new ReceiveActivity and SendActivity that marry Windows Workflow Foundation (WF) and Windows Communication Foundation (WCF) are really cool . Getting started is easy because a new Sequential Workflow Service Library, found under WCF instead of Workflow in VS2008, uses nice defaults for everything. But sooner or later you need to change these defaults and you need to know what can be done and what can't.
When you want to use the new ReceiveActivity in a workflow you need to use a compatible WCF binding. The reason for this requirement is that the conversation context, see this blog post, is part of the message and needs to be retrieved and returned. The following code returns a list of all WCF binding and how they are composed:
Dim assemblies As
New List(Of Assembly)()
' .NET 3.0
' .NET 3.5
Dim query = From assembly In assemblies _
From type In assembly.GetTypes() _
Where type.IsSubclassOf(GetType(Binding)) _
Not type.IsAbstract _
AndAlso type.IsPublic _
By type.Name _
Sub PrintBinding(ByVal types As List(Of Type))
Each type In types
Dim binding As Binding = _
Dim elements = binding.CreateBindingElements
Each element In elements
Console.WriteLine(vbTab + element.GetType().FullName)
Catch ex As Exception
The classes responsible for inserting and removing these conversation tokens are ContextRequestChannel and ContextReplyChannel and they are instantiated by the ContextBindingElement. So seems we are restricted to using BasicHttpContextBinding, NetTcpContextBinding or WSHttpContextBinding.
So it seems we cannot use NetMsmqBinding which is a shame because one way reliable messaging is the perfect fit for workflow as far as I am concerned. Well not quite so fast because we still have the CustomBinding where we can configure the stack just the way we want right?
Yeah we do but there is a problem . It turns out the ContextBinding requires a channel with an IReplyChannel interface and the NetMsmqBinding actually implement an IInputChannel or an IOutputChannel. Which one actually depends if you are the client or the service.
And thinking about how WF/WCF conversations works this restriction makes sense. After all a ReceiveActivity is called without a context in order to create a new workflow, assuming the CanCreateInstance property equals true, and returns the workflow instanceId in the context as part of the response. This design kind of rules out one-way messages and thereby NetMsmqBinding.
Now this sucks big time if you ask me . I would much rather have seen that you could specify the instanceId of the workflow to be created, just as you can with the WorkflowRuntime.CreateWorkflow() where a number of the overloads let you specify the workflows instanceId. I suppose it is possible to create a different context binding but that would be quite some work and, I assume, duplicate a lot of code already written my Microsoft. So let's hope they see the light and add MSMQ/ReceiveActivity intergration.