重用FormBuilder

时间:2017-12-09 20:14:40

标签: c# botframework

我的机器人会收到一些用户信息,例如订单号,以及基于搜索订单的其他一些细节。如果返回的订单超过1个,则会要求用户提供更多信息,以便提供2个额外的详细信息。

现在我的问题是因为我已经使用FormBuilder构建了表单并且在完成时我要求用户提供更多信息,以便应该是要求其他信息的方法。我应该创建另一个表单并请求信息,还是有办法在完成方法中将其他字段添加到同一表单。

我想在初始搜索完成后要求更多用户输入,并显示超过1个订单的msg。

作为我的属性SubOrderNumber& SubOrderVersion在OrderQuery类中,所以我应该为OrderQuery构建新表单还是有其他方法将这两个表单添加到现有的Order表单。

using System;
using Microsoft.Bot.Builder.FormFlow;

namespace Bot
{
    [Serializable]
    public class OrderSearchQuery
    {
        [Prompt("Please enter {&}")]
        public string OrderNumber { get; set; }

        [Prompt("Please enter {&}?")]
        public String Location { get; set; }

        [Prompt("Please provide last status {&}?")]
        public string Status{ get; set; }

        [Prompt("Please enter {&}?")]
        public string SubOrderNumber { get; set; }

        [Prompt("Please enter {&}?")]
        public string SubOrderVersion { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;
using Microsoft.Bot.Connector;

namespace Bot.Dialogs
{
    [Serializable]
    public class OrderDialog : IDialog<object>
    {

        public async Task StartAsync(IDialogContext context)
        {
            await context.PostAsync("Welcome to the Order helper!");

            var orderFormDialog = FormDialog.FromForm(this.BuildOrderForm, FormOptions.PromptInStart);

            context.Call(orderFormDialog, this.ResumeAfterOrdersFormDialog);
        }

        private IForm<OrderSearchQuery> BuildOrderForm()
        {
            OnCompletionAsyncDelegate<OrderSearchQuery> processOrderSearch = async (context, state) =>
            {
                await context.PostAsync($"Ok. Searching for Orders with Number: {state.OrderNumber}...");
            };

            return new FormBuilder<OrderSearchQuery>()
                .Field(nameof(OrderSearchQuery.OrderNumber))
                .AddRemainingFields(new string[] { nameof(RequiredDWPSearchQuery.SubOrderNumber), nameof(RequiredDWPSearchQuery.SubOrderVersion) })
                .OnCompletion(processOrderSearch)
                .Build();
        }

        private async Task ResumeAfterOrdersFormDialog(IDialogContext context, IAwaitable<OrderSearchQuery> result)
        {
            try
            {
                var searchQuery = await result;

                await context.PostAsync($"I found total of 100 Ordes");

                await context.PostAsync($"To get Order details, you will need to provide more info...");

}
            catch (FormCanceledException ex)
            {
                string reply;

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

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

    }
}

1 个答案:

答案 0 :(得分:0)

虽然有字段的条件参数和在验证中做逻辑的可能性,但我认为这不是最干净的方法。我会采取两种对话方式。

这是原始表单,删除了其他参数:

using Microsoft.Bot.Builder.FormFlow;
using System;

namespace TestChatbot.Dialogs
{
    [Serializable]
    public class OrderSearchQuery
    {
        [Prompt("Please enter {&}")]
        public string OrderNumber { get; set; }

        [Prompt("Please enter {&}?")]
        public String Location { get; set; }

        [Prompt("Please provide last status {&}?")]
        public string Status { get; set; }
    }
}

相反,我将其他属性移动到新表单:

using Microsoft.Bot.Builder.FormFlow;
using System;

namespace TestChatbot.Dialogs
{
    [Serializable]
    public class OrderFollowUp
    {
        [Prompt("Please enter {&}?")]
        public string SubOrderNumber { get; set; }

        [Prompt("Please enter {&}?")]
        public string SubOrderVersion { get; set; }
    }
}

然后我添加逻辑来处理第二种形式,具体取决于搜索结果:

using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;

namespace TestChatbot.Dialogs
{
    [Serializable]
    public class RootDialog : IDialog<object>
    {
        public async Task StartAsync(IDialogContext context)
        {
            await context.PostAsync("Welcome to the Order helper!");

            var orderFormDialog = FormDialog.FromForm(this.BuildOrderForm, FormOptions.PromptInStart);

            context.Call(orderFormDialog, this.ResumeAfterOrdersFormDialog);
        }

        private IForm<OrderSearchQuery> BuildOrderForm()
        {
            return new FormBuilder<OrderSearchQuery>()
                .Build();
        }

        private IForm<OrderFollowUp> BuildFollowUpForm()
        {
            return new FormBuilder<OrderFollowUp>()
                .Build();
        }

        private async Task ResumeAfterOrdersFormDialog(IDialogContext context, IAwaitable<OrderSearchQuery> result)
        {
            try
            {
                var searchQuery = await result;
                await context.PostAsync($"Ok. Searching for Orders with Number: {searchQuery.OrderNumber}...");
                await context.PostAsync($"I found total of 100 Ordes");

                int searchResultCount = 2;

                if (searchResultCount > 1)
                {
                    await context.PostAsync($"To get Order details, you will need to provide more info...");
                    var followUpDialog = FormDialog.FromForm(this.BuildFollowUpForm, FormOptions.PromptInStart);

                    context.Call(followUpDialog, this.ResumeAfterFollowUpDialog);
                }
            }
            catch (FormCanceledException ex)
            {
                string reply;

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

                await context.PostAsync(reply);
            }
        }

        private async Task ResumeAfterFollowUpDialog(IDialogContext context, IAwaitable<OrderFollowUp> result)
        {
            await context.PostAsync($"Order complete.");
            context.Done<object>(null);
        }
    }
}

这里的不同之处在于我在第一个对话框完成后删除了OnCompletion调用并在恢复处理程序上处理了该逻辑。根据搜索结果,您可以调用第二个对话框,就像您第一个提取其他信息一样。