Microsoft Bot Framework:如何从其他对话框中调用带有Interface参数类的Dialog

时间:2017-06-21 15:04:56

标签: c# dialog botframework

任何人都知道如何在另一个对话框类中调用此类,我是使用microsoft bot框架的初学者。我从https://ankitbko.github.io/2017/03/human-handover-bot/获得了此代码,我需要从我的FormBuilder对话框中调用它。请帮我。我传递文本LiveChat来触发实时聊天对话框类。

我收到此错误

  

邮件失败:无效类型:预期   Microsoft.Bot.Connector.IMessageActivity,具有String Bot异常:   堆栈为空[文件类型'text / plain']

接口类对话框:

namespace AgentTransferBot
    {


        [Serializable]
        public class EchoDialog : IDialog<object>
        {
            private readonly IUserToAgent _userToAgent;

            public EchoDialog(IUserToAgent userToAgent)
            {
                _userToAgent = userToAgent;
            }

            public async Task StartAsync(IDialogContext context)
            {
                context.Wait(MessageReceived);
            }

            private async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> result)
            {
                var message = await result;

                if (message.Text.StartsWith("LiveChat"))
                {
                    var agent = await _userToAgent.IntitiateConversationWithAgentAsync(message as Activity, default(CancellationToken));
                    if (agent == null)
                        await context.PostAsync("All our customer care representatives are busy at the moment. Please try after some time.");
                }
                else
                {
                    await context.PostAsync(message.Text);
                }
                context.Done(true);
            }
        }
    }

RootDialog类

namespace AgentTransferBot.Dialog
{
    [Serializable]
    public class RootDialog : IDialog<object>
    {
        private const string Existing = "Existing Customer";
        private const string NewCustomer = "New Application";

        public async Task StartAsync(IDialogContext context)
        {
            context.Wait(this.MessageReceivedAsync);
        }

        public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
        {
            var message = await result;

            if(message.Text.ToLower().Contains("help") || message.Text.ToLower().Contains("support") || message.Text.ToLower().Contains("problem"))
            {
                //await context.Forward(new SupportDialog(), this.ResumeAfterSupportDialog, message, CancellationToken.None);
            }
            else
            {
                this.ShowOptions(context);
            }
        }

        private void ShowOptions(IDialogContext context)
        {
            context.PostAsync("Welcome to X Company Customer Support!");

            PromptDialog.Choice(context, this.OnOptionSelected, new List<string>() { Existing, NewCustomer }, "Are you an existing or new customer?", "Not a valid option", 3);
        }

        private async Task OnOptionSelected(IDialogContext context, IAwaitable<string> result)
        {
            try
            {
                string optionSelected = await result;

                switch (optionSelected)
                {
                    case Existing:
                        context.Call(new ExistingDialog(), this.ResumeAfterOptionDialog);
                        break;
                    case NewCustomer:
                        //context.Call();
                        break;
                }
            }

            catch (TooManyAttemptsException ex)
            {
                await context.PostAsync($"Ooops! Too many attemps :(. But don't worry, I'm handling that exception and you can try again!");

                context.Wait(this.MessageReceivedAsync);
            }
        }

        private async Task ResumeAfterSupportDialog(IDialogContext context, IAwaitable<int> result)
        {
            var ticketNumber = await result;

            await context.PostAsync($"Thanks for contacting our support team. Your ticket number is {ticketNumber}.");
            context.Wait(this.MessageReceivedAsync);
        }

        private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
        {
            try
            {
                var message = await result;
            }
            catch(Exception ex)
            {
                await context.PostAsync($"Failed with message: {ex.Message}");
            }
            finally
            {
                context.Wait(this.MessageReceivedAsync);
            }
        }
    }
}

现有对话类:

    namespace AgentTransferBot.Dialog
    {
         private readonly IUserToAgent _userToAgent;
        [Serializable]
        public class ExistingDialog : IDialog<object>
        {
            public async Task StartAsync(IDialogContext context)
            {
                var existingCustomerDialog = FormDialog.FromForm(this.ExistingChoiceFormDialog, FormOptions.PromptInStart);

                context.Call(existingCustomerDialog, this.ResumeAfterExistingOptionDialog);
            }

            private IForm<ExistingQuestionsQuery> ExistingChoiceFormDialog()
            {
                OnCompletionAsyncDelegate<ExistingQuestionsQuery> processExistingChoices = async (context, state) =>
                {
                    var type = state.ExistingChoices.ToString();

                    if (state.ExistingChoices.Equals(ExistingChoices.Postpaid))
                    {
                        await context.PostAsync(type);
                    }

                    else if (state.ExistingChoices.Equals(ExistingChoices.Prepaid))
                    {
                        await context.PostAsync(type);
                    }

                    else if (state.ExistingChoices.Equals(ExistingChoices.LiveChat))
                    {
                        await context.Forward(new EchoDialog(_userToAgent), this.ResumeAfterSupportDialog, type, CancellationToken.None);
                    }

                };

                return new FormBuilder<ExistingQuestionsQuery>()
                    .Field(nameof(ExistingQuestionsQuery.PhoneNumber))
                    .Confirm("Is your phone number correct?: {PhoneNumber} {||}")
                    .AddRemainingFields()
                    .OnCompletion(processExistingChoices)
                    .Build();
            }

            private async Task ResumeAfterExistingOptionDialog(IDialogContext context, IAwaitable<ExistingQuestionsQuery> result)
            {
                try
                {
                    var existingQuery = await result;
                }
                catch (FormCanceledException ex)
                {
                    string reply;

                    if (ex.InnerException == null)
                    {
                        reply = "You have canceled the operation. Quitting from the Existing Dialog";
                    }
                    else
                    {
                        reply = $"Oops! Something went wrong :( Technical Details: {ex.InnerException.Message}";
                    }

                    await context.PostAsync(reply);
                }
                finally
                {
                    context.Done<object>(null);
                }
            }

            private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
            {
                try
                {
                    var message = await result;
                }
                catch (Exception ex)
                {
                    await context.PostAsync($"Failed with message: {ex.Message}");
                }
                finally
                {
                    context.Done(this);
                }
            }

        }
    }

IUserToAgent类

namespace AgentTransferBot
{
    public interface IUserToAgent
    {
        Task<bool> AgentTransferRequiredAsync(Activity message, CancellationToken cancellationToken);

        Task SendToAgentAsync(Activity message, CancellationToken cancellationToken);

        Task<Agent> IntitiateConversationWithAgentAsync(Activity message, CancellationToken cancellationToken);
    }
}

Controller.cs

namespace AgentTransferBot
{
    [BotAuthentication]
    public class MessagesController : ApiController
    {
        /// <summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>
        public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                await Conversation.SendAsync(activity, () => new RootDialog());

            }
            else
            {
                await HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }

        private async Task<Activity> HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
            else if (message.Type == ActivityTypes.Event)
            {
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var cancellationToken = default(CancellationToken);
                    var agentService = scope.Resolve<IAgentService>();
                    switch (message.AsEventActivity().Name)
                    {
                        case "connect":
                            await agentService.RegisterAgentAsync(message, cancellationToken);
                            break;
                        case "disconnect":
                            await agentService.UnregisterAgentAsync(message, cancellationToken);
                            break;
                        case "stopConversation":
                            await StopConversation(agentService, message, cancellationToken);
                            await agentService.RegisterAgentAsync(message, cancellationToken);
                            break;
                        default:
                            break;
                    }
                }
            }

            return null;
        }

        private async Task StopConversation(IAgentService agentService, Activity agentActivity, CancellationToken cancellationToken)
        {
            var user = await agentService.GetUserInConversationAsync(agentActivity, cancellationToken);
            var agentReply = agentActivity.CreateReply();
            if (user == null)
            {
                agentReply.Text = "Hey! You were not talking to anyone.";
                await SendToConversationAsync(agentReply);
                return;
            }

            var userActivity = user.ConversationReference.GetPostToBotMessage();
            await agentService.StopAgentUserConversationAsync(
                userActivity,
                agentActivity,
                cancellationToken);

            var userReply = userActivity.CreateReply();
            userReply.Text = "You have been disconnected from our representative.";
            await SendToConversationAsync(userReply);
            userReply.Text = "But we can still talk :)";
            await SendToConversationAsync(userReply);

            agentReply.Text = "You have stopped the conversation.";
            await SendToConversationAsync(agentReply);
        }

        private async Task SendAsync(IMessageActivity toBot, Func<ILifetimeScope, IDialog<object>> MakeRoot, CancellationToken token = default(CancellationToken))
        {
            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, toBot))
            {
                DialogModule_MakeRoot.Register(scope, () => MakeRoot(scope));
                var task = scope.Resolve<IPostToBot>();
                await task.PostAsync(toBot, token);
            }
        }
    }
}

ExistingQuery.cs

namespace AgentTransferBot.Queries
{

    public enum CustomerType
    {
        [Terms(new string[] { "Existing Customer", "New Application" })]
        Existing = 1,
        NewCustomer
    }

    public enum ExistingChoices
    {
        Postpaid = 1,
        Prepaid,
        [EnumMember(Value = "Live Chat")]
        LiveChat
    }

    [Serializable]
    public class ExistingQuestionsQuery
    {
        [Prompt("What is your phone number?")]
        public string PhoneNumber { get; set; }

        [Prompt("What is your plan type or do you want to talk to our represantives? {||}")]
        public ExistingChoices ExistingChoices { get; set; }
    }
}

0 个答案:

没有答案