locked
help to set the receive correlation in code RRS feed

  • Question

  • I am implementing a custom activity that contains receive and send reply activities.  When calling the receive operation from client, a correlation error is being thrown that the correlation for the activity is not set correctly:

     

    "A correlation query yielded an empty result set. Please ensure correlation queries for the endpoint are correctly configured."

     

    The custom activity class code is the following:

     

    public sealed class Activity1 : Activity
        {
            public Activity1()
            {
                this.Implementation = this.InternalImplementation;
            }

            public string OperationName { get; set; }
            public string ServiceContractName { get; set; }
            public bool CanCreateInstance { get; set; }
           
            private Activity InternalImplementation()
            {
                Variable<Process> requestMessage = new Variable<Process> { Name = "ProcessInstance" };
                Dictionary<string, OutArgument> paramList = new Dictionary<string, OutArgument>();
                paramList.Add("WorkflowArgs", new OutArgument<Process>(requestMessage));

                var messageQuerytable = new MessageQueryTable<string>();
                var path = new XPathMessageQuery("sm:body()/xg0:Process/xg0:PID", new XPathMessageContext());
                path.Namespaces.AddNamespace("xg0", "http://schemas.datacontract.org/2004/07/Taskflow.Entities");

                messageQuerytable.Add(path, "WorkflowOperation");
               
                Receive receive = new Receive
                {
                    OperationName = this.OperationName,
                    ServiceContractName=XName.Get(this.ServiceContractName,""),
                    CorrelatesOn = new System.ServiceModel.MessageQuerySet(messageQuerytable),
                    CanCreateInstance = CanCreateInstance,
                    Content = ReceiveContent.Create(paramList),
                };

                var reply = new SendReply()
                {
                    Request = receive,
                };

                return new Sequence
                {
                    Variables={requestMessage},
                    Activities =
                    {
                        new WriteLine { Text = "In Custom Activity" },

                        receive,
                       
                        reply,

                        new WriteLine { Text = "Custom Activity Complete" },
                    },
                };
            }
        }

     

    Please note that the ServiceContractName is set the same for all the receive activities in the workflow and the key for the correlation handle is set the same too.

     

    any help to solve this would be appreciated!

    bernadet.

    Thursday, September 23, 2010 11:52 AM

All replies

  • Hi,

    I am not sure of the specific issue in your sample, but it is a little different than the way I am familiar with setting correlation queries in code. Basically you want to tell the runtime where the piece of data is in the message that uniquely identifies the workflow instance for which the message is intended. I am used to doing it like this:

    Variable<string> OrderId = new Variable<string>();
    Variable<string> Item = new Variable<string>();
    Variable<CorrelationHandle> OrderIdHandle = new Variable<CorrelationHandle>();
    
    Receive StartOrder = new Receive
    {
      CanCreateInstance = true,
      ServiceContractName = "IOrderService",
      OperationName = "StartOrder"
    };
    
    SendReply ReplyToStartOrder = new SendReply
    {
      Request = StartOrder,
      Content = SendParametersContent.Create(new Dictionary<string, InArgument>
        { { "OrderId", new InArgument<string>((env) => OrderId.Get(env)) } }),
      CorrelationInitializers =
      {
        new QueryCorrelationInitializer
        {
          CorrelationHandle = OrderIdHandle,
          MessageQuerySet = new MessageQuerySet
          {
            {
              "OrderId", 
              new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
            }
          }
        }
      }
    };
    
    Receive AddItem = new Receive
    {
      ServiceContractName = "IOrderService",
      OperationName = "AddItem",
      CorrelatesWith = OrderIdHandle,
      CorrelatesOn = new MessageQuerySet
      {
        {
          "OrderId", 
           new XPathMessageQuery("sm:body()/tempuri:AddItem/tempuri:OrderId")
        }
      },
      Content = ReceiveParametersContent.Create(new Dictionary<string, OutArgument>
        { { "OrderId", new OutArgument<string>(OrderId) }, 
        { "Item", new OutArgument<string>(Item) } })
    };
    
    SendReply ReplyToAddItem = new SendReply
    {
      Request = AddItem,
      Content = SendParametersContent.Create(new Dictionary<string, InArgument>
        { { "Reply", new InArgument<string>((env) => "Item added: " + Item.Get(env)) } }),
    };
    
    // Construct a workflow using StartOrder, ReplyToStartOrder, and AddItem.
    

    (This sample code is from the Content Correlation topic)

    One thing that you can do to try and troubleshoot is to use WCF test Client, connect up and send the message, and then look at the xml to see what the message looks like and verify that the piece of data you are using is in the right place in the message and that the xpath correctly identifies where the data is.

    I didn't see the correlation handle in your code or where it was initialized, are you using implicit correlation handles? if not can you show how/where you initialize correlation?

    There are also some general troubleshooting steps in this topic: Troubleshooting Correlation.

    Let me know if the info above helps, and if not we can try some other things.

    Thanks,

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    • Proposed as answer by Andrew_Zhu Monday, September 27, 2010 8:48 AM
    Thursday, September 23, 2010 2:23 PM
  • Thank you Steve for your reply.

    Actually I am implementing one activity in the class, the correlation handle of the workflow is being initialized in the workflow designer.

    I have tried to pass the correlation variable to my custom activity through an InArgument<CorrelationHandle> and then set the CorrelatesWith property of the receive activity to this variable, but this exception came up in the designer:

     

    Error    1    The private implementation of activity '3: Activity1' has the following validation error:   The activity 'Receive' cannot reference activity 'VisualBasicValue<CorrelationHandle>' because activity 'VisualBasicValue<CorrelationHandle>' is already referenced elsewhere in the workflow and that reference is not visible to activity 'Receive'.  In order for activity 'VisualBasicValue<CorrelationHandle>' to be visible to activity 'Receive', it would have to be a child or imported child (but not an implementation child) of activity 'Activity1'.  Activity 'VisualBasicValue<CorrelationHandle>' is originally referenced by activity 'Activity1' and activity 'Receive' is in the implementation of activity 'Activity1'.

     

    I have refered to this post to solve it:

    http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/83414ffe-0b8a-456e-9bf3-c3c100f790fa

    but it doesn't help me to set the correlation correctly.

     

    thanks again!

     

    Friday, September 24, 2010 8:31 AM
  • Let me make sure I am understanding correctly. I am not sure if the problem is in the correlation, or if it is in the way that you are wrapping the Receive and SendReply inside the wrapper activity and flowing down the values. If you take the Receive/SendReply out of your custom activity and directly use them on the workflow (witht eh same property values, correlation query, etc...) does everything work properly? If so then your correlation query is correct and the problem is in the way that you are wrapping up the activities and passing down the properties. From looking at your code, I am not able to tell what the benefit of wrapping those two up in a custom activity? is it to provide less configuration for the workflow authors that use those activities? Before we look at that, can you take a look and let me know if the correlation works when you use the same two activities directly on a workflow? If that doesn't work, can you zip up a small project that has your activities and I will provide my email address and you can email it to me.

    Thanks,

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    Friday, September 24, 2010 5:13 PM
  • Hi Steve,

    Actually, i am implementing this custom activity to have the operation name of the receive activity set dynamically.

    I have added the Receive/SendReply in the designer and they worked perfectly with the correlation path set exactly the same as it is set in the code.

    It is really a strange thing as I have removed the SendReply activity from the sequence, having only the Receive activity in the sequence, and the call for the operation name worked successfully...

    I have looked to the service reference code too to compare between the operation names added from designer and from code, all the difference is the IsWrapped property of the Request class with the namespace, and if I set them exactly the same as the ones added from the designer, i get a time out exception when calling the operation name.

    I am really stuck with this issue, and have no idea how to resolve it :S

    Thanks for you help!

     

    Tuesday, September 28, 2010 9:31 AM
  • If you can zip up a sample that reproduces the problem and email it to me, I'll take a look, please send it to steve.danielson at microsoft.com

    Thanks

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    Tuesday, September 28, 2010 4:18 PM
  • Steve, I have a similar problem.  I have custom activity that schedules a Receive / SendReply activities along with other work that happens prior to and after the Recieve is executed.  I can't seem to get it to respect the WF instance correlation created by built-in Receive activity that created the correlation handle for the WF instance.  I'm getting the error:

    The execution of an InstancePersistenceCommand was interrupted because the instance key '12046dfc-8594-015f-430a-921927710e48' was not associated to an instance. This can occur because the instance or key has been cleaned up, or because the key is invalid. The key may be invalid if the message it was generated from was sent at the wrong time or contained incorrect correlation data.

    I'm not sure where its going wrong, either the CorrelatesOn or CorrelatesWith property of the Receive?  Looking at your example, I see how you're setting the CorrelatesOn property to the same/similar xpath string as what would be entered into the built-in Receive activity designer, however I'm not sure how Receive activity will get/see the WF instance variable for the correlation handle.  I suspect that's the problem.  In your example its already in your class whereas in my WF its an instance variable at the WF Service scope.


    Bruce Swan
    Tuesday, March 22, 2011 3:56 PM