private void ClientScheduleOnReceiveMessageCallback(NativeActivityContext executionContext, System.Activities.ActivityInstance completedInstance)
        {
            ReceiveMessageInstanceData instance = this.receiveMessageInstance.Get(executionContext).Instance;

            if (instance.CorrelationRequestContext.TryGetReply())
            {
                this.ClientScheduleOnReceiveMessageCore(executionContext, instance);
            }
            this.FinalizeScheduleOnReceivedMessage(executionContext, instance);
        }
        private void OnMessage(NativeActivityContext executionContext, Bookmark bookmark, object state)
        {
            WorkflowOperationContext context = state as WorkflowOperationContext;

            if (context == null)
            {
                throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.WorkflowMustBeHosted));
            }
            CorrelationResponseContext responseContext = new CorrelationResponseContext {
                WorkflowOperationContext = context
            };
            ReceiveMessageInstanceData instance = new ReceiveMessageInstanceData(responseContext);

            this.SetupTransaction(executionContext, instance);
        }
        protected override void Execute(NativeActivityContext executionContext)
        {
            CorrelationRequestContext context;
            CorrelationHandle         handle = (this.CorrelatesWith == null) ? null : this.CorrelatesWith.Get(executionContext);
            bool flag = false;
            CorrelationHandle ambientCorrelation = null;

            if (handle == null)
            {
                ambientCorrelation = executionContext.Properties.Find(CorrelationHandle.StaticExecutionPropertyName) as CorrelationHandle;
                flag = true;
                if (ambientCorrelation != null)
                {
                    handle = ambientCorrelation;
                }
            }
            if ((handle != null) && handle.TryAcquireRequestContext(executionContext, out context))
            {
                ReceiveMessageInstanceData instance = new ReceiveMessageInstanceData(context);
                if (flag)
                {
                    instance.SetAmbientCorrelation(ambientCorrelation);
                }
                this.ClientScheduleOnReceivedMessage(executionContext, instance);
            }
            else
            {
                if (ambientCorrelation == null)
                {
                    ambientCorrelation = executionContext.Properties.Find(CorrelationHandle.StaticExecutionPropertyName) as CorrelationHandle;
                }
                if ((!this.IsOneWay && (ambientCorrelation == null)) && (CorrelationHandle.GetExplicitChannelCorrelation(executionContext, this.correlationInitializers) == null))
                {
                    throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.ReceiveMessageNeedsToPairWithSendMessageForTwoWayContract(this.OperationName)));
                }
                BookmarkScope scope = (handle != null) ? handle.EnsureBookmarkScope(executionContext) : executionContext.DefaultBookmarkScope;
                if (this.onMessageBookmarkCallback == null)
                {
                    this.onMessageBookmarkCallback = new BookmarkCallback(this.OnMessage);
                }
                executionContext.CreateBookmark(this.OperationBookmarkName, this.onMessageBookmarkCallback, scope);
            }
        }
        private void SetupTransaction(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            WorkflowOperationContext workflowOperationContext = instance.CorrelationResponseContext.WorkflowOperationContext;

            if (workflowOperationContext.CurrentTransaction != null)
            {
                RuntimeTransactionHandle handle = null;
                handle = executionContext.Properties.Find(runtimeTransactionHandlePropertyName) as RuntimeTransactionHandle;
                if (handle == null)
                {
                    throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.ReceiveNotWithinATransactedReceiveScope));
                }
                TransactedReceiveData data = executionContext.Properties.Find(TransactedReceiveData.TransactedReceiveDataExecutionPropertyName) as TransactedReceiveData;
                if ((data != null) && this.AdditionalData.IsFirstReceiveOfTransactedReceiveScopeTree)
                {
                    data.InitiatingTransaction = workflowOperationContext.OperationContext.TransactionFacet.Current;
                }
                Transaction currentTransaction = handle.GetCurrentTransaction(executionContext);
                if (currentTransaction != null)
                {
                    if (!currentTransaction.Equals(workflowOperationContext.CurrentTransaction))
                    {
                        throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.FlowedTransactionDifferentFromAmbient));
                    }
                    this.ServerScheduleOnReceivedMessage(executionContext, instance);
                }
                else
                {
                    ReceiveMessageState state = new ReceiveMessageState {
                        CurrentTransaction = workflowOperationContext.CurrentTransaction.Clone(),
                        Instance           = instance
                    };
                    handle.RequireTransactionContext(executionContext, new Action <NativeActivityTransactionContext, object>(this.RequireContextCallback), state);
                }
            }
            else
            {
                this.ServerScheduleOnReceivedMessage(executionContext, instance);
            }
        }
        void ProcessReceiveMessageTrace(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            if (TraceUtility.MessageFlowTracing)
            {
                if (TraceUtility.ActivityTracing)
                {
                    instance.AmbientActivityId = InternalReceiveMessage.TraceCorrelationActivityId;
                }

                Guid receivedActivityId = Guid.Empty;
                if (instance.CorrelationRequestContext != null)
                {
                    //client side reply
                    receivedActivityId = TraceUtility.GetReceivedActivityId(instance.CorrelationRequestContext.OperationContext);
                }
                else if (instance.CorrelationResponseContext != null)
                {
                    //server side receive
                    receivedActivityId = instance.CorrelationResponseContext.WorkflowOperationContext.E2EActivityId;
                }

                ProcessReceiveMessageTrace(executionContext, receivedActivityId);
            }
        }
        // Phase 3: Setup Transaction for server receive case.
        // 
        void SetupTransaction(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            WorkflowOperationContext workflowContext = instance.CorrelationResponseContext.WorkflowOperationContext;
            if (workflowContext.CurrentTransaction != null)
            {
                //get the RuntimeTransactionHandle from the ambient
                RuntimeTransactionHandle handle = null;
                handle = executionContext.Properties.Find(runtimeTransactionHandlePropertyName) as RuntimeTransactionHandle;
                if (handle != null)
                {
                    //You are probably inside a TransactedReceiveScope
                    //TransactedReceiveData is used to pass information about the Initiating Transaction to the TransactedReceiveScope 
                    //so that it can subsequently call Complete or Commit on it at the end of the scope
                    TransactedReceiveData transactedReceiveData = executionContext.Properties.Find(TransactedReceiveData.TransactedReceiveDataExecutionPropertyName) as TransactedReceiveData;
                    if (transactedReceiveData != null)
                    {
                        if (this.AdditionalData.IsFirstReceiveOfTransactedReceiveScopeTree)
                        {
                            Fx.Assert(workflowContext.OperationContext != null, "InternalReceiveMessage.SetupTransaction - Operation Context was null");
                            Fx.Assert(workflowContext.OperationContext.TransactionFacet != null, "InternalReceiveMessage.SetupTransaction - Transaction Facet was null");
                            transactedReceiveData.InitiatingTransaction = workflowContext.OperationContext.TransactionFacet.Current;
                        }
                    }

                    Transaction currentTransaction = handle.GetCurrentTransaction(executionContext);
                    if (currentTransaction != null) 
                    {
                        if (!currentTransaction.Equals(workflowContext.CurrentTransaction))
                        {
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.FlowedTransactionDifferentFromAmbient));
                        }
                        else
                        {
                            ServerScheduleOnReceivedMessage(executionContext, instance);
                            return;
                        }
                    }

                    ReceiveMessageState receiveMessageState = new ReceiveMessageState
                    {
                        CurrentTransaction = workflowContext.CurrentTransaction.Clone(),
                        Instance = instance
                    };

                    handle.RequireTransactionContext(executionContext, RequireContextCallback, receiveMessageState);

                    return;
                }
                else
                {
                    //Receive was probably not used within a TransactionFlowScope since no ambient transaction handle was found
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.ReceiveNotWithinATransactedReceiveScope));
                }
            }

            ServerScheduleOnReceivedMessage(executionContext, instance);
        }
        // Phase 2a: server side message has arrived and resumed the protocol bookmark
        void OnMessage(NativeActivityContext executionContext, Bookmark bookmark, object state)
        {
            WorkflowOperationContext workflowContext = state as WorkflowOperationContext;

            if (workflowContext == null)
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.WorkflowMustBeHosted));
            }

            ReceiveMessageInstanceData instance = new ReceiveMessageInstanceData(
                new CorrelationResponseContext
                {
                    WorkflowOperationContext = workflowContext,
                });

            SetupTransaction(executionContext, instance);
        }
        // Activity Entry point: Phase 1: Execute
        // A separate code-path for extension based execution least impacts 
        // the existing workflow hosts. In the future we will add an extension from 
        // workflowservicehost and always use the extension.
        protected override void Execute(NativeActivityContext executionContext)
        {
            SendReceiveExtension sendReceiveExtension = executionContext.GetExtension<SendReceiveExtension>();
            if (sendReceiveExtension != null)
            {
                this.ExecuteUsingExtension(sendReceiveExtension, executionContext);
            }
            else
            {

                // this activity's runtime DU particpation(UpdateInstance) is dependent on
                // the following server side logic for resolving CorrelationHandle and creating a protocol bookmark.

                CorrelationHandle followingCorrelation = (this.CorrelatesWith == null) ? null : this.CorrelatesWith.Get(executionContext);
                bool triedAmbientCorrelation = false;
                CorrelationHandle ambientCorrelation = null;

                if (followingCorrelation == null)
                {
                    ambientCorrelation = executionContext.Properties.Find(CorrelationHandle.StaticExecutionPropertyName) as CorrelationHandle;
                    triedAmbientCorrelation = true;
                    if (ambientCorrelation != null)
                    {
                        followingCorrelation = ambientCorrelation;
                    }
                }

                CorrelationRequestContext requestContext;
                if (followingCorrelation != null && followingCorrelation.TryAcquireRequestContext(executionContext, out requestContext))
                {
                    // Client receive that is following a send.
                    ReceiveMessageInstanceData instance = new ReceiveMessageInstanceData(requestContext);

                    // for perf, cache the ambient correlation information
                    if (triedAmbientCorrelation)
                    {
                        instance.SetAmbientCorrelation(ambientCorrelation);
                    }

                    ClientScheduleOnReceivedMessage(executionContext, instance);
                }
                else
                {
                    // Server side receive

                    // Validation of correlatesWithHandle
                    if (ambientCorrelation == null)
                    {
                        ambientCorrelation = executionContext.Properties.Find(CorrelationHandle.StaticExecutionPropertyName) as CorrelationHandle;
                    }
                    if (!this.IsOneWay && ambientCorrelation == null)
                    {
                        CorrelationHandle channelCorrelationHandle = CorrelationHandle.GetExplicitRequestReplyCorrelation(executionContext, this.correlationInitializers);
                        if (channelCorrelationHandle == null)
                        {
                            // With a two-way contract, we require a request/reply correlation handle
                            throw FxTrace.Exception.AsError(new InvalidOperationException(
                                SR2.ReceiveMessageNeedsToPairWithSendMessageForTwoWayContract(this.OperationName)));
                        }
                    }

                    BookmarkScope bookmarkScope = (followingCorrelation != null) ? followingCorrelation.EnsureBookmarkScope(executionContext) : executionContext.DefaultBookmarkScope;

                    if (this.onMessageBookmarkCallback == null)
                    {
                        this.onMessageBookmarkCallback = new BookmarkCallback(this.OnMessage);
                    }

                    executionContext.CreateBookmark(this.OperationBookmarkName, this.onMessageBookmarkCallback, bookmarkScope);
                }
            }
        }        
        // Phase 5: Useful for the both client and server side receive. It passes down the response context if it is two way or 
        // throw the exception right back to the workflow if it is not expected. 
        void FinalizeReceiveMessageCore(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            if (instance != null)
            {
                if (instance.CorrelationRequestContext != null && instance.CorrelationRequestContext.Reply != null)
                {
                    // This should be closed by the formatter after desrializing the message
                    // clean this reply message up for a following receive
                    //instance.CorrelationRequestContext.Reply.Close();
                }
                else if (instance.CorrelationResponseContext != null)
                {
                    // this is only for the server side
                    if (this.IsOneWay)
                    {
                        // mark this workflow service operation as complete
                        instance.CorrelationResponseContext.WorkflowOperationContext.SetOperationCompleted();

                        if (instance.CorrelationResponseContext.Exception != null)
                        {
                            // We got an unexpected exception while running the OnReceivedMessage action
                            throw FxTrace.Exception.AsError(instance.CorrelationResponseContext.Exception);
                        }
                    }
                }

                //reset the trace
                this.ResetTrace(executionContext, instance);
            }
        }
        void ClientScheduleOnReceiveMessageCore(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            Fx.Assert(instance.CorrelationRequestContext.Reply != null, "Reply message cannot be null!");

            // Initialize CorrelationContext and CorrelationCallbackContext
            instance.InitializeContextAndCallbackContext();

            CorrelationHandle ambientHandle = instance.GetAmbientCorrelation(executionContext);

            if (instance.CorrelationRequestContext.CorrelationKeyCalculator != null)
            {
                // Client side reply do not use CorrelatesWith to initialize correlation
                instance.CorrelationRequestContext.Reply = MessagingActivityHelper.InitializeCorrelationHandles(executionContext,
                    null, ambientHandle, this.correlationInitializers,
                    instance.CorrelationRequestContext.CorrelationKeyCalculator, instance.CorrelationRequestContext.Reply);
            }

            // for the duplex-case 
            // we would receive the Server Context in the Request-Reply message, we have to save the Server Context so that subsequent sends from the client to
            // the server can use this context to reach the correct Server instance
            if (instance.CorrelationContext != null)
            {
                // Pass the CorrelationContext to correlation handle.
                // Correlation handle will have to be in the correlation Initializers collection
                CorrelationHandle contextHandle = CorrelationHandle.GetExplicitContextCorrelation(executionContext, this.correlationInitializers);

                // if that is not set, then try the ambient handle
                if (contextHandle == null)
                {
                    // get the cached ambient handle, we only use explicit handle or ambient handle to store the context
                    contextHandle = ambientHandle;
                }
                if (contextHandle != null)
                {
                    contextHandle.Context = instance.CorrelationContext;
                }
            }

            // set the Message with what is in the correlationRequestContext 
            // this Message needs to be closed later by the formatter
            Message request = instance.CorrelationRequestContext.Reply;
            this.Message.Set(executionContext, request);
        }
        private void ServerScheduleOnReceivedMessage(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            System.ServiceModel.Channels.Message message = instance.CorrelationResponseContext.WorkflowOperationContext.Inputs[0] as System.ServiceModel.Channels.Message;
            this.Message.Set(executionContext, message);
            instance.CorrelationResponseContext.MessageVersion = ((System.ServiceModel.Channels.Message)instance.CorrelationResponseContext.WorkflowOperationContext.Inputs[0]).Version;
            CorrelationHandle ambientCorrelation = instance.GetAmbientCorrelation(executionContext);
            CorrelationHandle selectHandle       = (this.CorrelatesWith == null) ? null : this.CorrelatesWith.Get(executionContext);

            MessagingActivityHelper.InitializeCorrelationHandles(executionContext, selectHandle, ambientCorrelation, this.correlationInitializers, instance.CorrelationResponseContext.WorkflowOperationContext.OperationContext.IncomingMessageProperties);
            CorrelationHandle explicitChannelCorrelation = CorrelationHandle.GetExplicitChannelCorrelation(executionContext, this.correlationInitializers);

            if (this.IsOneWay)
            {
                if (explicitChannelCorrelation != null)
                {
                    throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.RequestReplyHandleShouldNotBePresentForOneWay));
                }
                if (this.NoPersistHandle != null)
                {
                    System.Activities.NoPersistHandle handle4 = this.NoPersistHandle.Get(executionContext);
                    if (handle4 != null)
                    {
                        handle4.Enter(executionContext);
                    }
                }
            }
            else if (explicitChannelCorrelation != null)
            {
                if (!explicitChannelCorrelation.TryRegisterResponseContext(executionContext, instance.CorrelationResponseContext))
                {
                    throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.TryRegisterRequestContextFailed));
                }
            }
            else if (!ambientCorrelation.TryRegisterResponseContext(executionContext, instance.CorrelationResponseContext))
            {
                throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.ReceiveMessageNeedsToPairWithSendMessageForTwoWayContract(this.OperationName)));
            }
            if (instance.CorrelationCallbackContext != null)
            {
                CorrelationHandle explicitCallbackCorrelation = CorrelationHandle.GetExplicitCallbackCorrelation(executionContext, this.correlationInitializers);
                if (explicitCallbackCorrelation == null)
                {
                    explicitCallbackCorrelation = ambientCorrelation;
                }
                if (explicitCallbackCorrelation != null)
                {
                    explicitCallbackCorrelation.CallbackContext = instance.CorrelationCallbackContext;
                }
            }
            this.FinalizeScheduleOnReceivedMessage(executionContext, instance);
        }
 private void ProcessReceiveMessageTrace(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
 {
     if (TraceUtility.MessageFlowTracing)
     {
         try
         {
             if (TraceUtility.ActivityTracing)
             {
                 instance.AmbientActivityId = Trace.CorrelationManager.ActivityId;
             }
             Guid empty = Guid.Empty;
             if (instance.CorrelationRequestContext != null)
             {
                 empty = TraceUtility.GetReceivedActivityId(instance.CorrelationRequestContext.OperationContext);
             }
             else if (instance.CorrelationResponseContext != null)
             {
                 empty = instance.CorrelationResponseContext.WorkflowOperationContext.E2EActivityId;
             }
             ReceiveMessageRecord record = new ReceiveMessageRecord("MessageCorrelationReceiveRecord")
             {
                 E2EActivityId = empty
             };
             executionContext.Track(record);
             if ((empty != Guid.Empty) && (DiagnosticTrace.ActivityId != empty))
             {
                 DiagnosticTrace.ActivityId = empty;
             }
             System.ServiceModel.Activities.FxTrace.Trace.SetAndTraceTransfer(executionContext.WorkflowInstanceId, true);
             if (TraceUtility.ActivityTracing && System.ServiceModel.Activities.TD.StartSignpostEventIsEnabled())
             {
                 Dictionary <string, string> dictionary = new Dictionary <string, string>(3);
                 dictionary.Add("ActivityName", base.DisplayName);
                 dictionary.Add("ActivityType", "MessagingActivityExecution");
                 dictionary.Add("ActivityInstanceId", executionContext.ActivityInstanceId);
                 System.ServiceModel.Activities.TD.StartSignpostEvent(new DictionaryTraceRecord(dictionary));
             }
         }
         catch (Exception exception)
         {
             if (Fx.IsFatal(exception))
             {
                 throw;
             }
             System.ServiceModel.Activities.FxTrace.Exception.AsInformation(exception);
         }
     }
 }
        private void FinalizeScheduleOnReceivedMessage(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            this.ProcessReceiveMessageTrace(executionContext, instance);
            IList <IReceiveMessageCallback> callbacks = MessagingActivityHelper.GetCallbacks <IReceiveMessageCallback>(executionContext.Properties);

            if ((callbacks != null) && (callbacks.Count > 0))
            {
                OperationContext operationContext = instance.GetOperationContext();
                foreach (IReceiveMessageCallback callback in callbacks)
                {
                    callback.OnReceiveMessage(operationContext, executionContext.Properties);
                }
            }
            this.FinalizeReceiveMessageCore(executionContext, instance);
        }
 private void FinalizeReceiveMessageCore(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
 {
     if (instance != null)
     {
         if (((instance.CorrelationRequestContext == null) || (instance.CorrelationRequestContext.Reply == null)) && ((instance.CorrelationResponseContext != null) && this.IsOneWay))
         {
             instance.CorrelationResponseContext.WorkflowOperationContext.SetOperationCompleted();
             if (instance.CorrelationResponseContext.Exception != null)
             {
                 throw System.ServiceModel.Activities.FxTrace.Exception.AsError(instance.CorrelationResponseContext.Exception);
             }
         }
         if (TraceUtility.ActivityTracing)
         {
             if (System.ServiceModel.Activities.TD.StopSignpostEventIsEnabled())
             {
                 Dictionary <string, string> dictionary = new Dictionary <string, string>(3);
                 dictionary.Add("ActivityName", base.DisplayName);
                 dictionary.Add("ActivityType", "MessagingActivityExecution");
                 dictionary.Add("ActivityInstanceId", executionContext.ActivityInstanceId);
                 System.ServiceModel.Activities.TD.StopSignpostEvent(new DictionaryTraceRecord(dictionary));
             }
             System.ServiceModel.Activities.FxTrace.Trace.SetAndTraceTransfer(instance.AmbientActivityId, true);
             instance.AmbientActivityId = Guid.Empty;
         }
     }
 }
        // Phase 4: Set up the Message as OutArgument and invoke the OnReceivedMessage activity action
        void ServerScheduleOnReceivedMessage(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            Fx.Assert(instance.CorrelationResponseContext != null, "Server side receive must have CorrelationResponseContext");

            // if we infer the contract as Message the first input parameter will be the requestMessage from the client
            Message request = instance.CorrelationResponseContext.WorkflowOperationContext.Inputs[0] as Message;
            Fx.Assert(request != null, "WorkflowOperationContext.Inputs[0] must be of type Message");
            Fx.Assert(request.State == MessageState.Created, "The request message must be in Created state");
            this.Message.Set(executionContext, request);

            // update instance->CorrelationResponseContext with the MessageVersion information, this is later used by 
            // ToReply formatter to construct the reply message
            instance.CorrelationResponseContext.MessageVersion = ((Message)instance.CorrelationResponseContext.WorkflowOperationContext.Inputs[0]).Version;

            // initialize the relevant correlation handle(s) with the 'anonymous' response context
            CorrelationHandle ambientHandle = instance.GetAmbientCorrelation(executionContext);
            CorrelationHandle correlatesWithHandle = (this.CorrelatesWith == null) ? null : this.CorrelatesWith.Get(executionContext);

            // populate instance keys first
            MessagingActivityHelper.InitializeCorrelationHandles(executionContext, correlatesWithHandle, ambientHandle, this.correlationInitializers,
                instance.CorrelationResponseContext.WorkflowOperationContext.OperationContext.IncomingMessageProperties);

            // for the request/reply handle
            // then store the response context in the designated correlation handle
            // first check for an explicit association
            CorrelationHandle channelCorrelationHandle = CorrelationHandle.GetExplicitRequestReplyCorrelation(executionContext, this.correlationInitializers);

            
            if (this.IsOneWay)
            {
                // this is one way, verify that the channelHandle is null
                if (channelCorrelationHandle != null)
                {
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.RequestReplyHandleShouldNotBePresentForOneWay));
                }

                // we need to enter the nopersistzone using the NoPersistHandle and exit it in the formatter
                if (this.NoPersistHandle != null)
                {
                    NoPersistHandle noPersistHandle = this.NoPersistHandle.Get(executionContext);
                    if (noPersistHandle != null)
                    {
                        noPersistHandle.Enter(executionContext);
                    }
                }
            }
            else 
            {
                // first check for an explicit association
                if (channelCorrelationHandle != null)
                {
                    if (!channelCorrelationHandle.TryRegisterResponseContext(executionContext, instance.CorrelationResponseContext))
                    {
                        throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.TryRegisterRequestContextFailed));
                    }
                }
                else// if that fails, use ambient handle. we should never initialize CorrelatesWith with response context
                {
                    Fx.Assert(ambientHandle != null, "Ambient handle should not be null for two-way server side receive/sendReply");
                    if (!ambientHandle.TryRegisterResponseContext(executionContext, instance.CorrelationResponseContext))
                    {
                        // With a two-way contract, the request context must be initialized
                        throw FxTrace.Exception.AsError(new InvalidOperationException(
                            SR2.ReceiveMessageNeedsToPairWithSendMessageForTwoWayContract(this.OperationName)));
                    }
                }

                // validate that NoPersistHandle is null, we should have nulled it out in Receive->SetIsOneWay during ContractInference
                Fx.Assert(this.NoPersistHandle == null, "NoPersistHandle should be null in case of two-way");
            }
        
            // for the duplex handle: we want to save the callback context in the correlation handle
            if (instance.CorrelationCallbackContext != null)
            {
                // Pass the CorrelationCallbackContext to correlation handle.
                CorrelationHandle callbackHandle = CorrelationHandle.GetExplicitCallbackCorrelation(executionContext, this.correlationInitializers);

                // if that is not set, then try the ambientHandle, we will not use the CorrelatesWith handle  to store callback context
                if (callbackHandle == null)
                {
                    callbackHandle = ambientHandle;
                }
                if (callbackHandle != null)
                {
                    callbackHandle.CallbackContext = instance.CorrelationCallbackContext;
                }
            }

            FinalizeScheduleOnReceivedMessage(executionContext, instance);
        }
        void ClientScheduleOnReceivedMessage(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            Fx.Assert(instance.CorrelationRequestContext != null, "Client side receive must have CorrelationRequestContext");

            // client side: retrieve the reply from the request context
            if (instance.CorrelationRequestContext.TryGetReply())
            {
                // Reply has already come back because one of the following happened:
                // (1) Receive reply completed synchronously
                // (2) Async receive reply completed very quickly and channel callback already happened by now
                ClientScheduleOnReceiveMessageCore(executionContext, instance);
                FinalizeScheduleOnReceivedMessage(executionContext, instance);
            }
            else
            {
                // Async path: wait for reply to come back
                VolatileReceiveMessageInstance volatileInstance = new VolatileReceiveMessageInstance { Instance = instance };
                this.receiveMessageInstance.Set(executionContext, volatileInstance);

                if (onClientReceiveMessageComplete == null)
                {
                    onClientReceiveMessageComplete = new CompletionCallback(ClientScheduleOnReceiveMessageCallback);
                }

                executionContext.ScheduleActivity(this.waitForReply, onClientReceiveMessageComplete);
            }
        }
 private void ClientScheduleOnReceivedMessage(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
 {
     if (instance.CorrelationRequestContext.TryGetReply())
     {
         this.ClientScheduleOnReceiveMessageCore(executionContext, instance);
         this.FinalizeScheduleOnReceivedMessage(executionContext, instance);
     }
     else
     {
         VolatileReceiveMessageInstance instance2 = new VolatileReceiveMessageInstance {
             Instance = instance
         };
         this.receiveMessageInstance.Set(executionContext, instance2);
         if (this.onClientReceiveMessageComplete == null)
         {
             this.onClientReceiveMessageComplete = new CompletionCallback(this.ClientScheduleOnReceiveMessageCallback);
         }
         executionContext.ScheduleActivity(this.waitForReply, this.onClientReceiveMessageComplete);
     }
 }
        void FinalizeScheduleOnReceivedMessage(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            ProcessReceiveMessageTrace(executionContext, instance);

            IList<IReceiveMessageCallback> receiveMessageCallbacks = MessagingActivityHelper.GetCallbacks<IReceiveMessageCallback>(executionContext.Properties);
            if (receiveMessageCallbacks != null && receiveMessageCallbacks.Count > 0)
            {
                OperationContext operationContext = instance.GetOperationContext();
                // invoke the callback that user might have added in the AEC in the previous activity 
                // e.g. distributed compensation activity will add this so that they can convert a message back to
                // an execution property
                foreach (IReceiveMessageCallback receiveMessageCallback in receiveMessageCallbacks)
                {
                    receiveMessageCallback.OnReceiveMessage(operationContext, executionContext.Properties);
                }
            }

            // call this method with or without callback
            this.FinalizeReceiveMessageCore(executionContext, instance);
        }
                public WaitForReplyAsyncResult(ReceiveMessageInstanceData instance, AsyncCallback callback, object state)
                    : base(callback, state)
                {
                    if (onReceiveReply == null)
                    {
                        onReceiveReply = new Action<object, TimeoutException>(OnReceiveReply);
                    }

                    if (instance.CorrelationRequestContext.WaitForReplyAsync(onReceiveReply, this))
                    {
                        Complete(true);
                    }
                }
        void ResetTrace(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            this.ResetTrace(executionContext, instance.AmbientActivityId);

            if (TraceUtility.ActivityTracing)
            {
                instance.AmbientActivityId = Guid.Empty;
            }
        }
        private void ClientScheduleOnReceiveMessageCore(NativeActivityContext executionContext, ReceiveMessageInstanceData instance)
        {
            instance.InitializeContextAndCallbackContext();
            CorrelationHandle ambientCorrelation = instance.GetAmbientCorrelation(executionContext);

            if (instance.CorrelationRequestContext.CorrelationKeyCalculator != null)
            {
                instance.CorrelationRequestContext.Reply = MessagingActivityHelper.InitializeCorrelationHandles(executionContext, null, ambientCorrelation, this.correlationInitializers, instance.CorrelationRequestContext.CorrelationKeyCalculator, instance.CorrelationRequestContext.Reply);
            }
            if (instance.CorrelationContext != null)
            {
                CorrelationHandle explicitContextCorrelation = CorrelationHandle.GetExplicitContextCorrelation(executionContext, this.correlationInitializers);
                if (explicitContextCorrelation == null)
                {
                    explicitContextCorrelation = ambientCorrelation;
                }
                if (explicitContextCorrelation != null)
                {
                    explicitContextCorrelation.Context = instance.CorrelationContext;
                }
            }
            System.ServiceModel.Channels.Message reply = instance.CorrelationRequestContext.Reply;
            this.Message.Set(executionContext, reply);
        }