Content Correlation within a Native Activity Difficulties
-
Wednesday, April 11, 2012 2:58 AM
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):
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>
- Edited by Mr. Heizenburg Wednesday, April 11, 2012 4:19 AM
All Replies
-
Sunday, April 15, 2012 7:26 AM
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.
-
Wednesday, April 18, 2012 3:19 AM
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.

