locked
Correlation - how to ? RRS feed

  • Question

  • What are the differences between the correlation types available in WF ? Is there any document available for describing it?

    I have a client app that deals with multimple WorkflowApplications ( ex WfInstances) hosted together in the same service. This client app sends various messages to different applications ( the client app initiates the communications). In this scenario shall I use content based correlation? How can I set up this type of correlation based on the InstanceID.

    Thank you
    Sunday, November 1, 2009 12:01 PM

Answers

  • Hi Victor:

    In client side, assume you have a variable call "AppInstanceID", which is the instance id of client workflow instance.
    Drag and drop a Send and set the MessageContent to AppInstanceID. Of course you also need to configure the Operation, ServiceContract and Endpoint in the Send accordingly to your scenario. The XAML is something like:

      <p:Send OperationName="SomeOperation" ServiceContractName="SomeContract">
        <p:SendMessageContent>
          <InArgument x:TypeArguments="x:string">[AppInstanceID]</InArgument>
        </p:SendMessageContent>
      </p:Send>

    In service side, you should have a first Receive to receive the message sent by client. assume you have a variable call "AppInstanceID" to store the received value from client. And you also need to a variable of type CorrelationHandle to store the correlation information, let's called it "InstanceIdCorrHandle".
    And configure the first Receive like:

        <p:Receive CanCreateInstance="True" DisplayName="FirstReceive" >
          <p:Receive.CorrelationInitializers>
            <p:QueryCorrelationInitializer CorrelationHandle="[InstanceIdCorrHandle]">
              <p:XPathMessageQuery x:Key="key1">
                <p:XPathMessageQuery.Namespaces>
                  <ssx:XPathMessageContextMarkup>
                    <x:String x:Key="xg0">http://schemas.microsoft.com/2003/10/Serialization/</x:String>
                  </ssx:XPathMessageContextMarkup>
                </p:XPathMessageQuery.Namespaces>sm:body()/xg0:string</p:XPathMessageQuery>
            </p:QueryCorrelationInitializer>
          </p:Receive.CorrelationInitializers>
          <p:ReceiveMessageContent>
            <OutArgument x:TypeArguments="x:String">[AppInstanceID]</OutArgument>
          </p:ReceiveMessageContent>
        </p:Receive>

    The key idea of the first receive is using a QueryCorrelationInitializer to initialize the InstanceIdCorrHandle, with the value send by client.

    Then you might have second Recive want to follow the first Receive, assume the call from client is same as the first call. You need a Receive like:

        <p:Receive CanCreateInstance="True" CorrelatesWith="[InstanceIdCorrHandle]" DisplayName="SecondReceive" >
          <p:Receive.CorrelatesOn>
            <p:XPathMessageQuery x:Key="key1">
              <p:XPathMessageQuery.Namespaces>
                <ssx:XPathMessageContextMarkup>
                  <x:String x:Key="xg0">http://schemas.microsoft.com/2003/10/Serialization/</x:String>
                </ssx:XPathMessageContextMarkup>
              </p:XPathMessageQuery.Namespaces>sm:body()/xg0:string</p:XPathMessageQuery>
          </p:Receive.CorrelatesOn>
          <p:ReceiveMessageContent>
            <OutArgument x:TypeArguments="x:String">[AppInstanceID]</OutArgument>
          </p:ReceiveMessageContent>
        </p:Receive>

    The key idea of second receive is using the CorrelationWith to specify whicn CorrelationHandle you want to follow, using the CorrelationOn to specify how to follow the handle.

    You actually don't need to write the XPATH yourself, you can using the designer the generate the XPATH for you. Just click ... button of each property in the property grid.

    Because the steps might be very long, so i didn't give you step by step instruction. Hope you can figure out it yourself. Sorry about that.
    Let me know you have other questions.
    Wednesday, November 4, 2009 2:44 PM

All replies

  • Let me clarify your scenario first.
    You want your Workflow Client App to talk with multiple different Workflow Service App. But you want to use the content based correlation. One of the correlation key/value is the Instance ID of your Workflow Client App.

    If that is your scenario. Yes you can use the content based correlation. But since you need to get the Instance ID inside the workflow, you need to create a custom activity for get the Instance ID, such as

        public sealed class GetInstanceID : CodeActivity
        {
            public OutArgument<string> InstanceID { get; set; }

            protected override void Execute(CodeActivityContext context)
            {
                this.InstanceID.Set(context, context.WorkflowInstanceId.ToString());
            }
        }

    You also need to send the Client Instance ID to each service side, to let them initialize the correlation handle by Client Instance ID.

    Thanks
    Hong

    Sunday, November 1, 2009 8:38 PM
  • Hi Hong,

    Yes, this is the scenario I want to implement. The GetInstanceID activity is already in place and working so all the client apps have the correspondent InstanceID.
    The question still remains though. How do I set up the correlation?
    I have created a new CorrelationHandle and I have the AppInstanceID. Which one of the CorrelatesWith, CorrelatesOn, CorrelationInitializers properties do I have to set and how? What's the login behind this?

    Thank's
    Monday, November 2, 2009 9:11 AM
  • The most difficult part I have is setting right the correct XPATH for a specific correlation. In various code samples ( Beta 2 samples, MSDN Documentation ) I've found usage XPATH expressions like this :

    "sm:body()/defns:PurchaseOrder/defns:Id"
    "sm:body()/defns:StartOrderResponse/defns:OrderId"
    "sm:body()/ser:int"
    "sm:body()/xgSc:JoinWorkflowResponse/xgSc:AppIID"  -  this one is generated automatically in the designer

    I've tryed in many ways to set the XPATH right but i'm always getting an exception about invalid namespace when I'm opening the workflow service host. Whatever I try to use or modify in the namespace the result is the same. How can I set the same namespace to the entire WCF service. I must mention I'm using the designer when editing activities, not the programatic model.
    Monday, November 2, 2009 11:14 PM
  • Hi Victor:

    In client side, assume you have a variable call "AppInstanceID", which is the instance id of client workflow instance.
    Drag and drop a Send and set the MessageContent to AppInstanceID. Of course you also need to configure the Operation, ServiceContract and Endpoint in the Send accordingly to your scenario. The XAML is something like:

      <p:Send OperationName="SomeOperation" ServiceContractName="SomeContract">
        <p:SendMessageContent>
          <InArgument x:TypeArguments="x:string">[AppInstanceID]</InArgument>
        </p:SendMessageContent>
      </p:Send>

    In service side, you should have a first Receive to receive the message sent by client. assume you have a variable call "AppInstanceID" to store the received value from client. And you also need to a variable of type CorrelationHandle to store the correlation information, let's called it "InstanceIdCorrHandle".
    And configure the first Receive like:

        <p:Receive CanCreateInstance="True" DisplayName="FirstReceive" >
          <p:Receive.CorrelationInitializers>
            <p:QueryCorrelationInitializer CorrelationHandle="[InstanceIdCorrHandle]">
              <p:XPathMessageQuery x:Key="key1">
                <p:XPathMessageQuery.Namespaces>
                  <ssx:XPathMessageContextMarkup>
                    <x:String x:Key="xg0">http://schemas.microsoft.com/2003/10/Serialization/</x:String>
                  </ssx:XPathMessageContextMarkup>
                </p:XPathMessageQuery.Namespaces>sm:body()/xg0:string</p:XPathMessageQuery>
            </p:QueryCorrelationInitializer>
          </p:Receive.CorrelationInitializers>
          <p:ReceiveMessageContent>
            <OutArgument x:TypeArguments="x:String">[AppInstanceID]</OutArgument>
          </p:ReceiveMessageContent>
        </p:Receive>

    The key idea of the first receive is using a QueryCorrelationInitializer to initialize the InstanceIdCorrHandle, with the value send by client.

    Then you might have second Recive want to follow the first Receive, assume the call from client is same as the first call. You need a Receive like:

        <p:Receive CanCreateInstance="True" CorrelatesWith="[InstanceIdCorrHandle]" DisplayName="SecondReceive" >
          <p:Receive.CorrelatesOn>
            <p:XPathMessageQuery x:Key="key1">
              <p:XPathMessageQuery.Namespaces>
                <ssx:XPathMessageContextMarkup>
                  <x:String x:Key="xg0">http://schemas.microsoft.com/2003/10/Serialization/</x:String>
                </ssx:XPathMessageContextMarkup>
              </p:XPathMessageQuery.Namespaces>sm:body()/xg0:string</p:XPathMessageQuery>
          </p:Receive.CorrelatesOn>
          <p:ReceiveMessageContent>
            <OutArgument x:TypeArguments="x:String">[AppInstanceID]</OutArgument>
          </p:ReceiveMessageContent>
        </p:Receive>

    The key idea of second receive is using the CorrelationWith to specify whicn CorrelationHandle you want to follow, using the CorrelationOn to specify how to follow the handle.

    You actually don't need to write the XPATH yourself, you can using the designer the generate the XPATH for you. Just click ... button of each property in the property grid.

    Because the steps might be very long, so i didn't give you step by step instruction. Hope you can figure out it yourself. Sorry about that.
    Let me know you have other questions.
    Wednesday, November 4, 2009 2:44 PM