bool StartProcessing()
        {
            bool          callAgain     = false;
            SendOperation sendOperation = this.messageRpc.Operations[0];

            this.currentClient = this.service.GetOrCreateClient <TContract>(sendOperation.CurrentEndpoint, this.messageRpc.Impersonating);

            if (TD.RoutingServiceTransmittingMessageIsEnabled())
            {
                TD.RoutingServiceTransmittingMessage(this.messageRpc.EventTraceActivity, this.messageRpc.UniqueID, "0", this.currentClient.Key.ToString());
            }

            try
            {
                if (messageRpc.Transaction != null && sendOperation.HasAlternate)
                {
                    throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.ErrorHandlingNotSupportedReqReplyTxn(this.messageRpc.OperationContext.Channel.LocalAddress)));
                }

                // We always work on cloned message when there are backup endpoints to handle exception cases
                Message message;
                if (sendOperation.AlternateEndpointCount > 0)
                {
                    message = messageRpc.CreateBuffer().CreateMessage();
                }
                else
                {
                    message = messageRpc.Message;
                }

                sendOperation.PrepareMessage(message);

                IAsyncResult result = null;
                using (this.PrepareTransactionalCall(messageRpc.Transaction))
                {
                    IDisposable impersonationContext = null;
                    try
                    {
                        //Perform the assignment in a finally block so it won't be interrupted asynchronously
                        try { }
                        finally
                        {
                            impersonationContext = messageRpc.PrepareCall();
                        }
                        result = this.currentClient.BeginOperation(message, messageRpc.Transaction, this.PrepareAsyncCompletion(operationCallback), this);
                    }
                    finally
                    {
                        if (impersonationContext != null)
                        {
                            impersonationContext.Dispose();
                        }
                    }
                }

                if (this.CheckSyncContinue(result))
                {
                    if (this.OperationComplete(result))
                    {
                        this.Complete(this.allCompletedSync);
                    }
                    else
                    {
                        callAgain = true;
                    }
                }
            }
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }

                if (!this.HandleClientOperationFailure(exception))
                {
                    throw;
                }
                callAgain = true;
            }
            return(callAgain);
        }
예제 #2
0
        bool SendToCurrentClient()
        {
            MessageRpc    messageRpc    = this.service.SessionMessages[this.sessionMessageIndex];
            SendOperation sendOperation = messageRpc.Operations[this.destinationIndex];

            if (sendOperation.Sent)
            {
                this.MoveToNextClientOperation(messageRpc.Operations.Count);
                return(true);
            }
            else if (!this.channelExtension.ReceiveContextEnabled &&
                     this.channelExtension.TransactedReceiveEnabled &&
                     sendOperation.HasAlternate)
            {
                // We can't do error handling for oneway Transactional unless there's RC.
                throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.ErrorHandlingNotSupportedTxNoRC(messageRpc.OperationContext.Channel.LocalAddress)));
            }

            RoutingEndpointTrait endpointTrait = sendOperation.CurrentEndpoint;

            this.client = this.service.GetOrCreateClient <TContract>(endpointTrait, messageRpc.Impersonating);
            try
            {
                // We always work on cloned message when there are backup endpoints to handle exception cases
                Message message;
                if (messageRpc.Operations.Count == 1 && sendOperation.AlternateEndpointCount == 0)
                {
                    message = messageRpc.Message;
                }
                else
                {
                    message = messageRpc.CreateBuffer().CreateMessage();
                }

                sendOperation.PrepareMessage(message);
                IAsyncResult result;

                if (TD.RoutingServiceTransmittingMessageIsEnabled())
                {
                    TD.RoutingServiceTransmittingMessage(messageRpc.EventTraceActivity, messageRpc.UniqueID, this.destinationIndex.ToString(TD.Culture), this.client.Key.ToString());
                }

                Transaction transaction = this.service.GetTransactionForSending(messageRpc);
                using (this.PrepareTransactionalCall(transaction))
                {
                    IDisposable impersonationContext = null;
                    try
                    {
                        //Perform the assignment in a finally block so it won't be interrupted asynchronously
                        try { }
                        finally
                        {
                            impersonationContext = messageRpc.PrepareCall();
                        }

                        result = this.client.BeginOperation(message, transaction, this.PrepareAsyncCompletion(clientOperationCallback), this);
                    }
                    finally
                    {
                        if (impersonationContext != null)
                        {
                            impersonationContext.Dispose();
                        }
                    }
                }

                if (this.CheckSyncContinue(result))
                {
                    this.ClientOperationComplete(result);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }

                //See if we can handle this Exception...
                if (this.HandleClientOperationFailure(exception))
                {
                    return(true);
                }
                throw;
            }
        }