On the WF ReceiveActivity and WCF bindings
Posted
Wednesday, March 26, 2008 6:46 PM
by
Maurice
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:
Sub Main()
Dim assemblies As
New List(Of Assembly)()
' .NET 3.0
assemblies.Add(GetType(ServiceHost).Assembly)
' .NET 3.5
assemblies.Add(GetType(WorkflowServiceHost).Assembly)
assemblies.Add(GetType(WebServiceHost).Assembly)
Dim query = From assembly In assemblies _
From type In assembly.GetTypes() _
Where type.IsSubclassOf(GetType(Binding)) _
AndAlso
Not type.IsAbstract _
AndAlso type.IsPublic _
Order
By type.Name _
Select type
PrintBinding(query.ToList)
Console.ReadLine()
End
Sub
Private
Sub PrintBinding(ByVal types As List(Of Type))
For
Each type In types
Console.WriteLine(type.FullName)
Try
Dim binding As Binding = _
CType(Activator.CreateInstance(type), Binding)
Dim elements = binding.CreateBindingElements
For
Each element In elements
Console.WriteLine(vbTab + element.GetType().FullName)
Next
Catch ex As Exception
Console.WriteLine(ex.Message)
End
Try
Console.WriteLine()
Next
End
Sub
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.
Enjoy!
www.TheProblemSolver.nl
http://wiki.WindowsWorkflowFoundation.eu