The Problem SolverWIndows Workflow Foundation
HomeShow ChangesPrintRecent ChangesSubscriptionsLost and FoundFind ReferencesRename

Search

History

18-3-2008 14:36:1118-3-2008 14:35:3811-3-2008 18:16:1511-3-2008 18:14:3211-3-2008 18:13:39

List all versions

Receive Activity
.
Summary

Using a ReceiveActivity is a great way of exposing a workflow via a WCF proxy.

Get started by creating a new project based upon "Sequential Workflow Service Library". This is found in the WCF projects node instead of the Worflow projects node!

Create a service interface, mine is nice and simple and add a few ReceiveActivity to the workflow and hoop up the service interface to the activities. No big deal so far and we can test things by just pressing F5 and having the WCF Test Client. Actually you can only call functions that are hooked up to an ReceiveActivity with the CanCreateInstance set to True so the WCF Test Client might not be all that useful here if you use multiple ReceiveActivity that are part of a single workflow or conversation.

Next step is to create a simple console application as a client with the following code:


Sub SimpleDemo()
		Dim proxy As New ServiceReference1.DoStuffClient
		Console.WriteLine(proxy.AskQuestion("Is this cool?"))
		proxy.AllDone()
End Sub

This code works just fine Smile until we decide to split it up and recreate the WCF proxy object for part two like this Sad:

Private Sub Part1()
		Dim proxy As New ServiceReference1.DoStuffClient
		proxy.GetStarted("Maurice")
		Console.WriteLine(proxy.AskQuestion("To be or not to be?"))
End Sub

Private Sub Part2()
		Dim proxy As New ServiceReference1.DoStuffClient
		Console.WriteLine(proxy.AskQuestion("Is this cool?"))
		proxy.AllDone()
End Sub

In this case the second proxy object doesn't work at all and we get a FaultException with the message "There is no context attached to incoming message for the service and the current operation is not marked with "CanCreateInstance = true". In order to communicate with this service check whether the incoming binding supports the context protocol and has a valid context initialized."

So what gives? Well the WCF service needs to know which workflow the request needs to be routed to and uses the WorkflowInstanceId to do so. When you create a proxu and do the first call this WorkflowInstanceId is automatically added and resent with the next request. So we need to retrieve this WorkflowInstanceId and, when we create the second proxy object, add it again. Doing so turns out to be pretty simple and only takes a few extra lines of code:

Private _instanceId As String

Private Sub Part1()
		Dim proxy As New ServiceReference1.DoStuffClient
		proxy.GetStarted("Maurice")
		Dim contextManager As IContextManager = _
		proxy.InnerChannel.GetProperty(Of IContextManager)()
		Dim context As Dictionary(Of String, String) = _
		contextManager.GetContext()
		_instanceId = context("instanceId")
		Console.WriteLine(proxy.AskQuestion("To be or not to be?"))
End Sub

 

Private Sub Part2()
		Dim proxy As New ServiceReference1.DoStuffClient
		Dim contextManager As IContextManager = _
		proxy.InnerChannel.GetProperty(Of IContextManager)()
		Dim context As New Dictionary(Of String, String)
		context.Add("instanceId", _instanceId)
		contextManager.SetContext(context)
		Console.WriteLine(proxy.AskQuestion("Is this cool?"))
		proxy.AllDone()
End Sub

Basically what we need to do is retrieve the workflow instanceId from the context that is returned with the first call and save that. Next time we create a new proxy object we need to store the same instanceId in the request context before we actually use it and we are good to go Smile Setting the instaceId is actually done through a ClientContextProtocol object which is returned as an IContextManager inside of the channel properties. Check the bold lines in the previous code sample.

So why is this so important?

Well one of the most powerful features of Workflow Foundation is its capability to have long running workflows. Now long running workflows would not be very useful if the client application needs to keep its proxy alive for as long as it need to communicate with the workflow. Guess that would make "long running" a very relative thing. But with this technique all the client has to do is save the workflow instanceId somewhere, perhaps a database table, and it can reconnect to the same workflow at a later point in time.

See
Wiki Usage

This wiki site is supposed to be a shared resource. As a shared resource everyone is encouraged to add new content or modify existing content!

Enjoy the WF wiki.

Recent Topics