Content Correlation within a Native Activity Difficulties

Unanswered Content Correlation within a Native Activity Difficulties

  • 11 เมษายน 2555 2:58
     
      มีโค้ด

    My Goal.  Encapsulate all messaging logic for all of my hosted Workflows.

    That is, hiding Message and Content correlation variables etc. from a Workflow Designer.

    To do this, I'm building a custom NativeActivity that schedules a Send/Receive, as well as a CorrelationScope activity.  All further workflow will be contained in the body of the CorrelationScope activity.

    Notes

    • I'm using SQL Persistance
    • I'm using the WorkflowInstanceID as my Content Correlation (I think this is the correct vocabulary)

    Issue

    Basically, I think the correlation handles are not being set within my CorrelationScope therefore the correlation hash's are not matching. Is there a better way to do this?

    Here is the error (Prettty standard error for content correlation gone wrong):

    Image 1

    Primary Workflow Xaml :

    <WorkflowService mc:Ignorable="sap" ConfigurationName="ServiceConfig" sap:VirtualizedContainerService.HintSize="266,290" Name="CustomTest" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/servicemodel" xmlns:dh="clr-namespace:DataLayer.HumanTaskModel;assembly=DataLayer" xmlns:h="clr-namespace:HostedWorkflow;assembly=HostedWorkflow" xmlns:h1="clr-namespace:HRWorkflow;assembly=HostedWorkflow" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:p="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sde="clr-namespace:System.Data.EntityClient;assembly=System.Data.Entity" xmlns:sdod="clr-namespace:System.Data.Objects.DataClasses;assembly=System.Data.Entity" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:ssa="clr-namespace:System.ServiceModel.Activities;assembly=System.ServiceModel.Activities" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <p:Sequence DisplayName="Sequential Service" sad:XamlDebuggerXmlReader.FileName="C:\Dev\Source\HRManager\HostedWorkflow\CustomTest.xamlx" sap:VirtualizedContainerService.HintSize="236,260" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces">
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <x:Boolean x:Key="IsExpanded">True</x:Boolean>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <h1:HumanTaskStartActivity sap:VirtualizedContainerService.HintSize="214,136">
          <h1:HumanTaskStartActivity.Body>
            <h:TaskReserveActivity sap:VirtualizedContainerService.HintSize="200,22" />
          </h1:HumanTaskStartActivity.Body>
        </h1:HumanTaskStartActivity>
      </p:Sequence>
    </WorkflowService>


    My Custom Activity:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Activities;
    using DataLayer;
    using System.ServiceModel.Activities;
    using System.ComponentModel;
    using System.ServiceModel;
    using Microsoft.VisualBasic.Activities;
    using System.Linq.Expressions;
    using System.Activities.Expressions;
    using HostedWorkflow;
    using System.Xml;
    
    namespace HRWorkflow
    {
         [Designer(typeof(HumanTaskStartActivityDesigner))]
        public sealed class HumanTaskStartActivity : NativeActivity
        {
            private Variable<CorrelationHandle> _SendReceiveCorrelationHandle = new Variable<CorrelationHandle>("_SendReceiveHandle");
    
            // Content (Instance) Correlation
             private Variable<Guid> _InstanceID = new Variable<Guid>("_InstanceID");
             private Variable<CorrelationHandle> ServiceInstanceCorrelationHandle {get;set;}
    
            private Receive _Receive;
            private SendReply _SendReply;
            private CreateTaskInstance _CreateHumanTaskInstance = new CreateTaskInstance();
            private CorrelationScope _CorrelationScope;
         
            public Activity Body{ get; set; }
    
            public HumanTaskStartActivity()     : base()
            {
                this.ServiceInstanceCorrelationHandle = new Variable<CorrelationHandle>("_WorkflowInstanceHandle");
                this._CorrelationScope = new CorrelationScope { CorrelatesWith = ServiceInstanceCorrelationHandle };
                this.Body = this._CorrelationScope.Body;
            }
    
            protected override void CacheMetadata(NativeActivityMetadata metadata)
            {
                metadata.AddImplementationVariable(ServiceInstanceCorrelationHandle);
    
                _Receive = _Receive ?? new Receive();
                _SendReply = _SendReply ?? new SendReply();
                _Receive.CanCreateInstance = true;
                _Receive.ServiceContractName = "IHumanTaskService";
                _Receive.OperationName = "Start";
                _SendReply.Request = _Receive;
                _SendReply.PersistBeforeSend = true;
    
                // Add Implementation Variables
                metadata.AddImplementationChild(_Receive);
                metadata.AddImplementationChild(_SendReply);
                metadata.AddImplementationVariable(_InstanceID);
                metadata.AddImplementationChild(_CorrelationScope);
                metadata.AddChild(this.Body);
                metadata.AddImplementationChild(_CreateHumanTaskInstance);
                metadata.AddImplementationVariable(_SendReceiveCorrelationHandle);
    
    
                // Create the RequestReplyInitializer that handles correlation between the Send and Receive activities
                var requestReplyInitializer = new RequestReplyCorrelationInitializer()
                {
                    CorrelationHandle = _SendReceiveCorrelationHandle
                };
    
                // Add the RequestReplyInitializer to the Receive Activiites list of CorrelationInitializers
                _Receive.CorrelationInitializers.Add(requestReplyInitializer);
    
                var x = new XPathMessageQuery();
                x.Namespaces.AddNamespace("xg0","http://schemas.microsoft.com/2003/10/Serialization/");
                x.Expression = "sm:body()/xg0:guid";
    
      
                // Create the correlation initializer that correlates this service instance
                var instanceCorrelationInitializer = new QueryCorrelationInitializer
                {
    
                    CorrelationHandle = ServiceInstanceCorrelationHandle,
                      
                    MessageQuerySet = new MessageQuerySet
                    {
                        { "KeyInstanceIDStart", x} 
                        
                    }
                };
    
                // Add a Parameter that will send back the Workflow InstanceID that will be used as the service's correlation value
                 _SendReply.Content = new SendMessageContent { Message = new InArgument<Guid>(_InstanceID) };
    
                // Add the service instance correlation to the intializers of the SendReply activity
                _SendReply.CorrelationInitializers.Add(instanceCorrelationInitializer);
            }
    
            protected override void Execute(NativeActivityContext context)
            {
                
                _InstanceID.Set(context, context.WorkflowInstanceId);
                context.ScheduleActivity(_Receive, ReceiveCompleted);
    
            }
    
            private void ReceiveCompleted(NativeActivityContext context, ActivityInstance completedInstance)
            {
                context.ScheduleActivity(_SendReply,SendCompleted);
            }
    
            private void SendCompleted(NativeActivityContext context, ActivityInstance completedInstance)
            {
                context.ScheduleActivity(this._CreateHumanTaskInstance);
    
                context.ScheduleActivity(this.Body);
            }
    
        }
    }

    The child activity with a "Reserve" operation.

    <Activity mc:Ignorable="sap" x:Class="HostedWorkflow.TaskReserveActivity" sap:VirtualizedContainerService.HintSize="317,446" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:cas="clr-namespace:Custom.Activities.Statements" xmlns:dh="clr-namespace:DataLayer.HumanTaskModel;assembly=DataLayer" xmlns:local="clr-namespace:HostedWorkflow" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:p="http://tempuri.org/" xmlns:p1="http://schemas.microsoft.com/netfx/2009/xaml/servicemodel" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:s4="clr-namespace:System;assembly=System.ServiceModel" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:ssa="clr-namespace:System.ServiceModel.Activities;assembly=System.ServiceModel.Activities" xmlns:ssx="clr-namespace:System.ServiceModel.XamlIntegration;assembly=System.ServiceModel" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <Sequence sad:XamlDebuggerXmlReader.FileName="C:\Dev\Source\HRManager\HostedWorkflow\TaskReserveActivity.xaml" sap:VirtualizedContainerService.HintSize="277,406">
        <Sequence.Variables>
          <Variable x:TypeArguments="p1:CorrelationHandle" Name="__handle1" />
        </Sequence.Variables>
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <x:Boolean x:Key="IsExpanded">True</x:Boolean>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <p1:Receive x:Name="__ReferenceID0" sap:VirtualizedContainerService.HintSize="255,90" OperationName="Reserve" ServiceContractName="p:IHumanTaskService">
          <p1:Receive.CorrelatesOn>
            <p1:XPathMessageQuery x:Key="key1">
              <p1:XPathMessageQuery.Namespaces>
                <ssx:XPathMessageContextMarkup>
                  <x:String x:Key="xgSc">http://tempuri.org/</x:String>
                </ssx:XPathMessageContextMarkup>
              </p1:XPathMessageQuery.Namespaces>sm:body()/xgSc:Reserve/xgSc:ID</p1:XPathMessageQuery>
          </p1:Receive.CorrelatesOn>
          <p1:Receive.CorrelationInitializers>
            <p1:RequestReplyCorrelationInitializer CorrelationHandle="[__handle1]" />
          </p1:Receive.CorrelationInitializers>
          <p1:ReceiveParametersContent>
            <OutArgument x:TypeArguments="s:Guid" x:Key="ID" />
          </p1:ReceiveParametersContent>
        </p1:Receive>
        <p1:SendReply Request="{x:Reference __ReferenceID0}" DisplayName="SendReplyToReceive" sap:VirtualizedContainerService.HintSize="255,90" PersistBeforeSend="True">
          <p1:SendParametersContent />
        </p1:SendReply>
        <local:UpdateTaskInstance sap:VirtualizedContainerService.HintSize="255,22" NewState="[DataLayer.HumanTaskModel.HumanTaskStates.Reserved]" />
      </Sequence>
    </Activity>


    • แก้ไขโดย Mr. Heizenburg 11 เมษายน 2555 4:19
    •  

ตอบทั้งหมด

  • 15 เมษายน 2555 7:26
     
     

    Hi,

    A problem here is that parent activity and child activity didn't share the same correlation handler. You may authoring both activities via code, then you can encapsulate the logic without problem.

  • 18 เมษายน 2555 3:19
     
      มีโค้ด

    HI Franconia, I dont explicitly sent the Correlation Handle as the assignment is automatic (or should be) within a CorrelationScope activity.  All child Activities would be contained in the Correlationscope.Body.  The purpose of the CorrelationScope activity is to auto-assign the "CorrelatesWith" InArgument for Receive Activites.

    The CorrleationHandle for the Correlation Initializer is set here:

    var instanceCorrelationInitializer = new QueryCorrelationInitializer { CorrelationHandle = ServiceInstanceCorrelationHandle,

    ...

    The CorrelationHandle is then also set for the CorrelationScope here:

    this._CorrelationScope = new CorrelationScope { CorrelatesWith = ServiceInstanceCorrelationHandle };

    So from my view, the CorrelationHandle is being shared with the Child Activities through the CorrelationScope activity.

    Doesnt work though :(,   seems the CorrelationHandle value is not being propagated.