Esempio n. 1
0
        /// <summary>
        /// Tries to initiate a connection (1:1 conversation) by creating a request on behalf of
        /// the given requestor. This method does nothing, if a request for the same user already exists.
        /// </summary>
        /// <param name="requestor">The requestor conversation reference.</param>
        /// <param name="rejectConnectionRequestIfNoAggregationChannel">
        /// If true, will reject all requests, if there is no aggregation channel.</param>
        /// <returns>The result of the operation:
        /// - ConnectionRequestResultType.Created,
        /// - ConnectionRequestResultType.AlreadyExists,
        /// - ConnectionRequestResultType.NotSetup or
        /// - ConnectionRequestResultType.Error (see the error message for more details).
        /// </returns>
        public virtual ConnectionRequestResult CreateConnectionRequest(
            ConversationReference requestor, bool rejectConnectionRequestIfNoAggregationChannel = false)
        {
            if (requestor == null)
            {
                throw new ArgumentNullException("Requestor missing");
            }

            ConnectionRequestResult createConnectionRequestResult = null;

            RoutingDataManager.AddConversationReference(requestor);
            ConnectionRequest connectionRequest = new ConnectionRequest(requestor);

            if (RoutingDataManager.IsAssociatedWithAggregation(requestor))
            {
                createConnectionRequestResult = new ConnectionRequestResult()
                {
                    Type         = ConnectionRequestResultType.Error,
                    ErrorMessage = $"The given ConversationReference ({RoutingDataManager.GetChannelAccount(requestor)?.Name}) is associated with aggregation and hence invalid to request a connection"
                };
            }
            else
            {
                createConnectionRequestResult = RoutingDataManager.AddConnectionRequest(
                    connectionRequest, rejectConnectionRequestIfNoAggregationChannel);
            }

            return(createConnectionRequestResult);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a new message activity and populates it based on the given arguments.
        /// </summary>
        /// <param name="sender">The channel account of the sender.</param>
        /// <param name="recipient">The conversation reference of the recipient.</param>
        /// <param name="message">The message content.</param>
        /// <returns>A newly created message activity.</returns>
        public static IMessageActivity CreateMessageActivity(
            ChannelAccount sender, ConversationReference recipient, string message)
        {
            IMessageActivity messageActivity = Activity.CreateMessageActivity();

            if (sender != null)
            {
                messageActivity.From = sender;
            }

            if (recipient != null)
            {
                if (recipient.Conversation != null)
                {
                    messageActivity.Conversation = recipient.Conversation;
                }

                ChannelAccount recipientChannelAccount =
                    RoutingDataManager.GetChannelAccount(recipient);

                if (recipientChannelAccount != null)
                {
                    messageActivity.Recipient = recipientChannelAccount;
                }
            }

            messageActivity.Text = message;
            return(messageActivity);
        }
Esempio n. 3
0
        /// <summary>
        /// Creates a compact card for accepting/rejecting multiple requests.
        /// </summary>
        /// <param name="connectionRequests">The connection requests.</param>
        /// <param name="doAccept">If true, will create an accept card. If false, will create a reject card.</param>
        /// <param name="botName">The name of the bot (optional).</param>
        /// <returns>The newly created card.</returns>
        public static HeroCard CreateMultiConnectionRequestCard(
            IList <ConnectionRequest> connectionRequests, bool doAccept, string botName = null)
        {
            HeroCard card = new HeroCard()
            {
                Title = (doAccept
                    ? Strings.AcceptConnectionRequestsCardTitle
                    : Strings.RejectConnectionRequestCardTitle),
                Subtitle = (doAccept
                    ? Strings.AcceptConnectionRequestsCardInstructions
                    : Strings.RejectConnectionRequestsCardInstructions),
            };

            card.Buttons = new List <CardAction>();

            if (!doAccept && connectionRequests.Count > 1)
            {
                card.Buttons.Add(new CardAction()
                {
                    Title = Strings.RejectAll,
                    Type  = ActionTypes.ImBack,
                    Value = new Command(Commands.RejectRequest, new string[] { Command.CommandParameterAll }, botName).ToString()
                });
            }

            foreach (ConnectionRequest connectionRequest in connectionRequests)
            {
                ChannelAccount requestorChannelAccount =
                    RoutingDataManager.GetChannelAccount(connectionRequest.Requestor, out bool isBot);

                if (requestorChannelAccount == null)
                {
                    throw new ArgumentNullException("The channel account of the requestor is null");
                }

                string requestorChannelAccountName = string.IsNullOrEmpty(requestorChannelAccount.Name)
                    ? StringConstants.NoUserNamePlaceholder : requestorChannelAccount.Name;
                string requestorChannelId =
                    CultureInfo.CurrentCulture.TextInfo.ToTitleCase(connectionRequest.Requestor.ChannelId);
                string requestorChannelAccountId = requestorChannelAccount.Id;

                Command command =
                    Command.CreateAcceptOrRejectConnectionRequestCommand(connectionRequest, doAccept, botName);

                card.Buttons.Add(new CardAction()
                {
                    Title = string.Format(
                        Strings.RequestorDetailsItem,
                        requestorChannelAccountName,
                        requestorChannelId,
                        requestorChannelAccountId),
                    Type  = ActionTypes.ImBack,
                    Value = command.ToString()
                });
            }

            return(card);
        }
Esempio n. 4
0
        /// <summary>
        /// Routes the message in the given activity, if the sender is connected in a conversation.
        /// </summary>
        /// <param name="activity">The activity to handle.</param>
        /// <param name="addNameToMessage">If true, will add the name of the sender to the beginning of the message.</param>
        /// <returns>The result of the operation:
        /// - MessageRouterResultType.NoActionTaken, if no routing rule for the sender is found OR
        /// - MessageRouterResultType.OK, if the message was routed successfully OR
        /// - MessageRouterResultType.FailedToForwardMessage in case of an error (see the error message).
        /// </returns>
        public virtual async Task <MessageRoutingResult> RouteMessageIfSenderIsConnectedAsync(
            IMessageActivity activity, bool addNameToMessage = true)
        {
            ConversationReference sender     = CreateSenderConversationReference(activity);
            Connection            connection = RoutingDataManager.FindConnection(sender);

            MessageRoutingResult messageRoutingResult = new MessageRoutingResult()
            {
                Type       = MessageRoutingResultType.NoActionTaken,
                Connection = connection
            };

            if (connection != null)
            {
                ConversationReference recipient =
                    RoutingDataManager.Match(sender, connection.ConversationReference1)
                        ? connection.ConversationReference2 : connection.ConversationReference1;

                if (recipient != null)
                {
                    string message = activity.Text;

                    if (addNameToMessage)
                    {
                        string senderName = RoutingDataManager.GetChannelAccount(sender).Name;

                        if (!string.IsNullOrWhiteSpace(senderName))
                        {
                            message = $"{senderName}: {message}";
                        }
                    }

                    ResourceResponse resourceResponse = await SendMessageAsync(recipient, message);

                    if (resourceResponse != null)
                    {
                        messageRoutingResult.Type = MessageRoutingResultType.MessageRouted;

                        if (!RoutingDataManager.UpdateTimeSinceLastActivity(connection))
                        {
                            Logger.Log("Failed to update the time since the last activity property of the connection");
                        }
                    }
                    else
                    {
                        messageRoutingResult.Type         = MessageRoutingResultType.FailedToRouteMessage;
                        messageRoutingResult.ErrorMessage = $"Failed to forward the message to the recipient";
                    }
                }
                else
                {
                    messageRoutingResult.Type         = MessageRoutingResultType.Error;
                    messageRoutingResult.ErrorMessage = "Failed to find the recipient to forward the message to";
                }
            }

            return(messageRoutingResult);
        }
Esempio n. 5
0
        public static Command CreateAcceptOrRejectConnectionRequestCommand(
            ConnectionRequest connectionRequest, bool doAccept, string botName = null)
        {
            ChannelAccount requestorChannelAccount =
                RoutingDataManager.GetChannelAccount(connectionRequest.Requestor);

            return(new Command(
                       doAccept ? Commands.AcceptRequest : Commands.RejectRequest,
                       new string[] { requestorChannelAccount?.Id, connectionRequest.Requestor.Conversation?.Id },
                       botName));
        }
Esempio n. 6
0
        /// <summary>
        /// Sends the given message to the given recipient.
        /// </summary>
        /// <param name="recipient">The conversation reference of the recipient.</param>
        /// <param name="messageActivity">The message activity to send.</param>
        /// <returns>A valid resource response instance, if successful. Null in case of an error.</returns>
        public virtual async Task <ResourceResponse> SendMessageAsync(
            ConversationReference recipient, IMessageActivity messageActivity)
        {
            if (recipient == null)
            {
                Logger.Log("The conversation reference is null");
                return(null);
            }

            // We need the bot identity in the SAME CHANNEL/CONVERSATION as the RECIPIENT -
            // Otherwise, the platform (e.g. Slack) will reject the incoming message as it does not
            // recognize the sender
            ConversationReference botInstance =
                RoutingDataManager.FindBotInstanceForRecipient(recipient);

            if (botInstance == null || botInstance.Bot == null)
            {
                Logger.Log("Failed to find the bot instance");
                return(null);
            }

            messageActivity.From      = botInstance.Bot;
            messageActivity.Recipient = RoutingDataManager.GetChannelAccount(recipient);

            // Make sure the message activity contains a valid conversation ID
            if (messageActivity.Conversation == null)
            {
                messageActivity.Conversation = recipient.Conversation;
            }

            ConnectorClientMessageBundle bundle = new ConnectorClientMessageBundle(
                recipient.ServiceUrl, messageActivity, _microsoftAppCredentials);

            ResourceResponse resourceResponse = null;

            try
            {
                resourceResponse =
                    await bundle.ConnectorClient.Conversations.SendToConversationAsync(
                        (Activity)bundle.MessageActivity);
            }
            catch (UnauthorizedAccessException e)
            {
                Logger.Log($"Failed to send message: {e.Message}");
            }
            catch (Exception e)
            {
                Logger.Log($"Failed to send message: {e.Message}");
            }

            return(resourceResponse);
        }
Esempio n. 7
0
        /// <summary>
        /// Creates a large connection request card.
        /// </summary>
        /// <param name="connectionRequest">The connection request.</param>
        /// <param name="botName">The name of the bot (optional).</param>
        /// <returns>A newly created request card.</returns>
        public static HeroCard CreateConnectionRequestCard(
            ConnectionRequest connectionRequest, string botName = null)
        {
            if (connectionRequest == null || connectionRequest.Requestor == null)
            {
                throw new ArgumentNullException("The connection request or the conversation reference of the requestor is null");
            }

            ChannelAccount requestorChannelAccount =
                RoutingDataManager.GetChannelAccount(connectionRequest.Requestor);

            if (requestorChannelAccount == null)
            {
                throw new ArgumentNullException("The channel account of the requestor is null");
            }

            string requestorChannelAccountName = string.IsNullOrEmpty(requestorChannelAccount.Name)
                ? StringConstants.NoUserNamePlaceholder : requestorChannelAccount.Name;
            string requestorChannelId =
                CultureInfo.CurrentCulture.TextInfo.ToTitleCase(connectionRequest.Requestor.ChannelId);

            Command acceptCommand =
                Command.CreateAcceptOrRejectConnectionRequestCommand(connectionRequest, true, botName);
            Command rejectCommand =
                Command.CreateAcceptOrRejectConnectionRequestCommand(connectionRequest, false, botName);

            HeroCard card = new HeroCard()
            {
                Title    = Strings.ConnectionRequestTitle,
                Subtitle = string.Format(Strings.RequestorDetailsTitle, requestorChannelAccountName, requestorChannelId),
                Text     = string.Format(Strings.AcceptRejectConnectionHint, acceptCommand.ToString(), rejectCommand.ToString()),

                Buttons = new List <CardAction>()
                {
                    new CardAction()
                    {
                        Title = Strings.AcceptButtonTitle,
                        Type  = ActionTypes.ImBack,
                        Value = acceptCommand.ToString()
                    },
                    new CardAction()
                    {
                        Title = Strings.RejectButtonTitle,
                        Type  = ActionTypes.ImBack,
                        Value = rejectCommand.ToString()
                    }
                }
            };

            return(card);
        }
Esempio n. 8
0
        /// <summary>
        /// Checks the given activity and determines whether the message was addressed directly to
        /// the bot or not.
        ///
        /// Note: Only mentions are inspected at the moment.
        /// </summary>
        /// <param name="messageActivity">The message activity.</param>
        /// <param name="strict">Use false for channels that do not properly support mentions.</param>
        /// <returns>True, if the message was address directly to the bot. False otherwise.</returns>
        public bool WasBotAddressedDirectly(IMessageActivity messageActivity, bool strict = true)
        {
            bool botWasMentioned = false;

            if (strict)
            {
                Mention[] mentions = messageActivity.GetMentions();

                foreach (Mention mention in mentions)
                {
                    foreach (ConversationReference bot in _messageRouter.RoutingDataManager.GetBotInstances())
                    {
                        if (mention.Mentioned.Id.Equals(RoutingDataManager.GetChannelAccount(bot).Id))
                        {
                            botWasMentioned = true;
                            break;
                        }
                    }
                }
            }
            else
            {
                // Here we assume the message starts with the bot name, for instance:
                //
                // * "@<BOT NAME>..."
                // * "<BOT NAME>: ..."
                string botName = messageActivity.Recipient?.Name;
                string message = messageActivity.Text?.Trim();

                if (!string.IsNullOrEmpty(botName) && !string.IsNullOrEmpty(message) && message.Length > botName.Length)
                {
                    try
                    {
                        message         = message.Remove(botName.Length + 1, message.Length - botName.Length - 1);
                        botWasMentioned = message.Contains(botName);
                    }
                    catch (ArgumentOutOfRangeException e)
                    {
                        System.Diagnostics.Debug.WriteLine($"Failed to check if bot was mentioned: {e.Message}");
                    }
                }
            }

            return(botWasMentioned);
        }
Esempio n. 9
0
        /// <summary>
        /// Tries to resolve the name of the given user/bot instance.
        /// Will fallback to ID, if no name specified.
        /// </summary>
        /// <param name="conversationReference">The conversation reference, whose details to resolve.</param>
        /// <returns>The name or the ID of the given user/bot instance.</returns>
        protected virtual string GetNameOrId(ConversationReference conversationReference)
        {
            if (conversationReference != null)
            {
                ChannelAccount channelAccount =
                    RoutingDataManager.GetChannelAccount(conversationReference);

                if (channelAccount != null)
                {
                    if (!string.IsNullOrWhiteSpace(channelAccount.Name))
                    {
                        return(channelAccount.Name);
                    }

                    if (!string.IsNullOrWhiteSpace(channelAccount.Id))
                    {
                        return(channelAccount.Id);
                    }
                }
            }

            return(StringConstants.NoNameOrId);
        }
Esempio n. 10
0
        /// <summary>
        /// Handles the given connection request result.
        /// </summary>
        /// <param name="connectionRequestResult">The result to handle.</param>
        /// <returns>True, if the result was handled. False, if no action was taken.</returns>
        protected virtual async Task <bool> HandleConnectionRequestResultAsync(
            ConnectionRequestResult connectionRequestResult)
        {
            ConnectionRequest connectionRequest = connectionRequestResult?.ConnectionRequest;

            if (connectionRequest == null || connectionRequest.Requestor == null)
            {
                System.Diagnostics.Debug.WriteLine("No client to inform about the connection request result");
                return(false);
            }

            switch (connectionRequestResult.Type)
            {
            case ConnectionRequestResultType.Created:
                foreach (ConversationReference aggregationChannel
                         in _messageRouter.RoutingDataManager.GetAggregationChannels())
                {
                    ConversationReference botConversationReference =
                        _messageRouter.RoutingDataManager.FindConversationReference(
                            aggregationChannel.ChannelId, aggregationChannel.Conversation.Id, null, true);

                    if (botConversationReference != null)
                    {
                        IMessageActivity messageActivity = Activity.CreateMessageActivity();
                        messageActivity.Conversation = aggregationChannel.Conversation;
                        messageActivity.Recipient    = RoutingDataManager.GetChannelAccount(aggregationChannel);
                        messageActivity.Attachments  = new List <Attachment>
                        {
                            CommandCardFactory.CreateConnectionRequestCard(
                                connectionRequest,
                                RoutingDataManager.GetChannelAccount(
                                    botConversationReference)?.Name).ToAttachment()
                        };

                        await _messageRouter.SendMessageAsync(aggregationChannel, messageActivity);
                    }
                }

                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NotifyClientWaitForRequestHandling);

                return(true);

            case ConnectionRequestResultType.AlreadyExists:
                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NotifyClientDuplicateRequest);

                return(true);

            case ConnectionRequestResultType.Rejected:
                if (connectionRequestResult.Rejecter != null)
                {
                    await _messageRouter.SendMessageAsync(
                        connectionRequestResult.Rejecter,
                        string.Format(Strings.NotifyOwnerRequestRejected, GetNameOrId(connectionRequest.Requestor)));
                }

                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NotifyClientRequestRejected);

                return(true);

            case ConnectionRequestResultType.NotSetup:
                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NoAgentsAvailable);

                return(true);

            case ConnectionRequestResultType.Error:
                if (connectionRequestResult.Rejecter != null)
                {
                    await _messageRouter.SendMessageAsync(
                        connectionRequestResult.Rejecter,
                        string.Format(Strings.ConnectionRequestResultErrorWithResult, connectionRequestResult.ErrorMessage));
                }

                return(true);

            default:
                break;
            }

            return(false);
        }
Esempio n. 11
0
        /// <summary>
        /// Tries to establish a connection (1:1 chat) between the two given parties.
        ///
        /// Note that the conversation owner will have a new separate conversation reference in the created
        /// conversation, if a new direct conversation is created.
        /// </summary>
        /// <param name="conversationReference1">The conversation reference who owns the conversation (e.g. customer service agent).</param>
        /// <param name="conversationReference2">The other conversation reference in the conversation.</param>
        /// <param name="createNewDirectConversation">
        /// If true, will try to create a new direct conversation between the bot and the
        /// conversation owner (e.g. agent) where the messages from the other (client) conversation
        /// reference are routed.
        ///
        /// Note that this will result in the conversation owner having a new separate conversation
        /// reference in the created connection (for the new direct conversation).
        /// </param>
        /// <returns>
        /// The result of the operation:
        /// - ConnectionResultType.Connected,
        /// - ConnectionResultType.Error (see the error message for more details).
        /// </returns>
        public virtual async Task <ConnectionResult> ConnectAsync(
            ConversationReference conversationReference1,
            ConversationReference conversationReference2,
            bool createNewDirectConversation)
        {
            if (conversationReference1 == null || conversationReference2 == null)
            {
                throw new ArgumentNullException(
                          $"Neither of the arguments ({nameof(conversationReference1)}, {nameof(conversationReference2)}) can be null");
            }

            ConversationReference botInstance =
                RoutingDataManager.FindConversationReference(
                    conversationReference1.ChannelId, conversationReference1.Conversation.Id, null, true);

            if (botInstance == null)
            {
                return(new ConnectionResult()
                {
                    Type = ConnectionResultType.Error,
                    ErrorMessage = "Failed to find the bot instance"
                });
            }

            ConversationResourceResponse conversationResourceResponse = null;

            if (createNewDirectConversation)
            {
                ChannelAccount conversationReference1ChannelAccount =
                    RoutingDataManager.GetChannelAccount(
                        conversationReference1, out bool conversationReference1IsBot);

                ConnectorClient connectorClient = new ConnectorClient(
                    new Uri(conversationReference1.ServiceUrl), _microsoftAppCredentials);

                try
                {
                    conversationResourceResponse =
                        await connectorClient.Conversations.CreateDirectConversationAsync(
                            botInstance.Bot, conversationReference1ChannelAccount);
                }
                catch (Exception e)
                {
                    Logger.Log($"Failed to create a direct conversation: {e.Message}");
                    // Do nothing here as we fallback (continue without creating a direct conversation)
                }

                if (conversationResourceResponse != null &&
                    !string.IsNullOrEmpty(conversationResourceResponse.Id))
                {
                    // The conversation account of the conversation owner for this 1:1 chat is different -
                    // thus, we need to re-create the conversation owner instance
                    ConversationAccount directConversationAccount =
                        new ConversationAccount(id: conversationResourceResponse.Id);


                    conversationReference1 = new ConversationReference(
                        null,
                        conversationReference1IsBot ? null : conversationReference1ChannelAccount,
                        conversationReference1IsBot ? conversationReference1ChannelAccount : null,
                        directConversationAccount,
                        conversationReference1.ChannelId,
                        conversationReference1.ServiceUrl);

                    RoutingDataManager.AddConversationReference(conversationReference1);

                    RoutingDataManager.AddConversationReference(new ConversationReference(
                                                                    null,
                                                                    null,
                                                                    botInstance.Bot,
                                                                    directConversationAccount,
                                                                    botInstance.ChannelId,
                                                                    botInstance.ServiceUrl));
                }
            }

            Connection       connection    = new Connection(conversationReference1, conversationReference2);
            ConnectionResult connectResult =
                RoutingDataManager.ConnectAndRemoveConnectionRequest(connection, conversationReference2);

            connectResult.ConversationResourceResponse = conversationResourceResponse;

            return(connectResult);
        }
Esempio n. 12
0
        /// <summary>
        /// Tries to accept/reject a pending connection request.
        /// </summary>
        /// <param name="messageRouter">The message router.</param>
        /// <param name="messageRouterResultHandler">The message router result handler.</param>
        /// <param name="sender">The sender party (accepter/rejecter).</param>
        /// <param name="doAccept">If true, will try to accept the request. If false, will reject.</param>
        /// <param name="requestorChannelAccountId">The channel account ID of the user/bot whose request to accept/reject.</param>
        /// <param name="requestorConversationAccountId">The conversation account ID of the user/bot whose request to accept/reject.</param>
        /// <returns>The result.</returns>
        public async Task <AbstractMessageRouterResult> AcceptOrRejectRequestAsync(
            MessageRouter messageRouter, MessageRouterResultHandler messageRouterResultHandler,
            ConversationReference sender, bool doAccept,
            ChannelAccount requestorChannelAccountId, ConversationAccount requestorConversationAccountId)
        {
            AbstractMessageRouterResult messageRouterResult = new ConnectionRequestResult()
            {
                Type = ConnectionRequestResultType.Error
            };

            ConversationReference requestor =
                new ConversationReference(
                    null, requestorChannelAccountId, null, requestorConversationAccountId);

            ConnectionRequest connectionRequest =
                messageRouter.RoutingDataManager.FindConnectionRequest(requestor);

            if (connectionRequest == null)
            {
                // Try bot
                requestor.Bot  = requestor.User;
                requestor.User = null;

                connectionRequest =
                    messageRouter.RoutingDataManager.FindConnectionRequest(requestor);
            }

            if (connectionRequest != null)
            {
                Connection connection = null;

                if (sender != null)
                {
                    connection = messageRouter.RoutingDataManager.FindConnection(sender);
                }

                ConversationReference senderInConnection = null;
                ConversationReference counterpart        = null;

                if (connection != null && connection.ConversationReference1 != null)
                {
                    if (RoutingDataManager.Match(sender, connection.ConversationReference1))
                    {
                        senderInConnection = connection.ConversationReference1;
                        counterpart        = connection.ConversationReference2;
                    }
                    else
                    {
                        senderInConnection = connection.ConversationReference2;
                        counterpart        = connection.ConversationReference1;
                    }
                }

                if (doAccept)
                {
                    if (senderInConnection != null)
                    {
                        // The sender (accepter/rejecter) is ALREADY connected to another party
                        if (counterpart != null)
                        {
                            messageRouterResult.ErrorMessage = string.Format(
                                Strings.AlreadyConnectedWithUser,
                                RoutingDataManager.GetChannelAccount(counterpart)?.Name);
                        }
                        else
                        {
                            messageRouterResult.ErrorMessage = Strings.ErrorOccured;
                        }
                    }
                    else
                    {
                        bool createNewDirectConversation =
                            (_noDirectConversationsWithChannels == null ||
                             !(_noDirectConversationsWithChannels.Contains(sender.ChannelId.ToLower())));

                        // Try to accept
                        messageRouterResult = await messageRouter.ConnectAsync(
                            sender,
                            connectionRequest.Requestor,
                            createNewDirectConversation);
                    }
                }
                else
                {
                    // Note: Rejecting is OK even if the sender is alreay connected
                    messageRouterResult = messageRouter.RejectConnectionRequest(connectionRequest.Requestor, sender);
                }
            }
            else
            {
                messageRouterResult.ErrorMessage = Strings.FailedToFindPendingRequest;
            }

            return(messageRouterResult);
        }