Mar 022011
 

Correlation is a priceless feature of WF4 that allows you to correlate WCF messages of your workflow based on some unique data in a subsequent message. From a calling client’s perspective, the need for correlation looks would look like this:

  1. Client creates workflow instance with WCF message
  2. Workflow (service) responds indicating that the workflow instance is running
  3. At some point in the future, client wants to resume the same, now waiting, workflow instance with another WCF message

To implement the resumption of the same workflow instance requires that the client have some sort of identifier to get back to the same instance they left earlier. WF4 uses CorrelationHandles to accomplish this. Using the CorrelationHandle class and some send/receive message properties, clients can share some unique ID to get back to the same instance. From a calling client’s perspective, the same scenario as before with correlation looks like this:

  1. Client creates workflow instance with WCF message
  2. Workflow creates a correlation handle on some unique ID
  3. Workflow (service) responds with the unique ID, for later correlation use, also indicating that the workflow instance is running
  4. At some point in the future, client wants to resume the same, now waiting, workflow instance with another WCF message
  5. Client sends another WCF message, including the unique ID in the message
  6. Workflow responds to the incoming message, reads the unique ID from the message, and looks up the correct instance by the correlation handle corresponding to that unique ID
  7. The same instance created earlier resumes

You may be asking yourself, “So how do I do all this correlation stuff?” The following procedure will detail the necessary steps. The download link at the bottom of this post contains a sample project that has this sample already implemented.

Procedure:

  1. Start with a workflow with two separate ReceiveAndSendReply sequences.
  2. If a unique ID is not available for correlation in your workflow already, you can use the WorkflowInstanceId. Put the following code in a new activity, and add the activity between the Receive and SendReply activities in your workflow.
    public sealed class GetWorkflowInstanceId : CodeActivity
    {
        public OutArgument<Guid> WorkflowInstanceId { get; set; }
    
        protected override void Execute(CodeActivityContext context)
        {
            context.SetValue<Guid>(this.WorkflowInstanceId, context.WorkflowInstanceId);
        }
    }
  3. Create a new variable named WorkflowInstanceId of type System.Guid. image
  4. Create a new variable named WorkflowInstanceCorrelationHandle of type CorrelationHandle.
  5. Set the WorkflowInstanceId out argument on the GetWorkflowInstanceId activity to the newly created variable WorkflowInstanceId.
  6. Modify the SendReply activity Content to include the WorkflowInstanceId guid. This will give the client the unique ID to use in subsequent messages.
  7. Open the SendReply activity CorrelationInitializers with the ellipsis button.
  8. Click Add initializer in the left pane of the Add Correlation Initializers window. Type the name of the newly created variable WorkflowInstanceCorrectionHandle.
  9. Verify that Query correlation initializer is selected in the combo box. Double-click to add a key under XPath Queries. Choose the WorkflowInstanceId item from the outbound message/parameters. In the attached example, this appears after the double-click as “Content : Guid” and appears as “sm:body()/xg0:guid” as an XPath query.
    image
  10. Click OK to close the Add Correlation Initializers window.
  11. For the subsequent Receive activities, modify the Content to include the WorkflowInstanceId guid as either a message or parameter. This will make it possible to lookup the correct workflow instance.
  12. On the same Receive activities, open CorrelatesOn with the ellipsis button.
  13. Type the name of the variable WorkflowInstanceCorrelationHandle in the CorrelatesWith field.
  14. Double-click to add a key under XPath Queries. Choose the WorkflowInstanceId item from the outbound message/parameters. In the attached example, this appears after the double-click as “Content : Guid” and appears as “sm:body()/xg0:guid” as an XPath query.
    image
  15. Test the interaction by creating a test client (included in the download below) that creates 2 or more instances and resumes them in a different order.
  16. The final workflow should look like the image to the right.

Download WfCorrelation.zip – 25.1 KB (25,727 bytes)
(Build the solution before opening the workflow to avoid activity errors)

 Posted by at 5:45 am
Dec 142010
 

I started seeing the following error in the AppFabric exceptions appearing during activation of my WF workflow.

Cannot create unknown type '{clr-namespace:MyActivityLibrary}MyCodeActivity'

The workflow completed all the steps of MyCodeActivity and the other code activities in my activity library. WF never complained; it was only an error visible in AppFabric. A Bing search resulted in the following suggestions:

  1. Create separate class libraries for activities and workflows (xamlx): already done.
  2. Place the activity library in the GAC: that should not be necessary so I skipped that one.
  3. Remove and add the activity from the workflow: again not necessary because I can see in the xaml that the namespace and the activity are fine and not appearing as a local assembly.

So it must be something else. Perhaps the unknown type error is not telling me the whole story and maybe it is failing to load/create another type referenced by my library? I went through my references and found a reference to a DLL that is not used by my activities. I removed the unnecessary reference and the errors did not return. Maybe the same thing is happening to you.

 Posted by at 9:26 pm