c# - 在 Botframework V4 中扩展和链接对话框的正确方法?

标签 c# botframework

在我的 OnTurnAsync 中,我在一个单独的类中调用 Main Dialog。主对话框还从其他类调用其他对话框,依此类推。这是分离和扩展Dialog的正确方法吗?我每个人都制作了单独的组件对话框。因为我有很长的对话流程,并且在 Main Bot 类中完成所有对话很困惑。

主对话框:

public class MainDialog : ComponentDialog
{
    private const string InitialId = "mainDialog";
    private const string ChoicePrompt = "choicePrompt";
    private const string DialogAId = "dialogAId";

    public MainDialog(string dialogId)
        : base(dialogId)
    {
        InitialDialogId = InitialId;

        WaterfallStep[] waterfallSteps = new WaterfallStep[]
         {
            FirstStepAsync,
            SecondStepAsync,
            ContinueStepAsync,
            ThirdStepAsync,
         };
        AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
        AddDialog(new ChoicePrompt(ChoicePrompt));
        AddDialog(new DialogA(DialogAId));
    }

    private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        return await stepContext.PromptAsync(
            ChoicePrompt,
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"Here are your choices:"),
                Choices = new List<Choice>
                    {
                        new Choice
                        {
                            Value = "Open Dialog A",
                        },
                        new Choice
                        {
                            Value = "Open Dialog B",
                        },
                    },
                RetryPrompt = MessageFactory.Text($"Please choose one of the options."),
            });
    }

    private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        var response = (stepContext.Result as FoundChoice)?.Value.ToLower();

        if (response == "open dialog a")
        {
            return await stepContext.BeginDialogAsync(DialogAId, cancellationToken: cancellationToken);
        }

        if (response == "open dialog b")
        {
            // re-prompt not working btw
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Dialog B is not ready need to reprompt previous step."));
            await stepContext.RepromptDialogAsync();
        }

        return await stepContext.NextAsync();
    }

    private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        // what is the best way to end this?
        // return await stepContext.ReplaceDialogAsync(InitialId);
        return await stepContext.EndDialogAsync();
    }
}

对话框A代码:

 public class DialogA : ComponentDialog
{
    private const string InitialId = "dialogA";
    private const string ChoicePrompt = "choicePrompt";
    private const string DialogAchildId = "dialogA_childId";

    public DialogA(string dialogId)
        : base(dialogId)
    {
        InitialDialogId = InitialId;

        WaterfallStep[] waterfallSteps = new WaterfallStep[]
         {
            FirstStepAsync,
            SecondStepAsync,
            ContinueStepAsync,
            ThirdStepAsync,
         };
        AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
        AddDialog(new ChoicePrompt(ChoicePrompt));
        AddDialog(new DialogA_child(DialogAchildId));
    }

    private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        return await stepContext.PromptAsync(
            ChoicePrompt,
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"Here are your choices:"),
                Choices = new List<Choice>
                    {
                        new Choice
                        {
                            Value = "Open Dialog A_Child",
                        },
                        new Choice
                        {
                            Value = "Open Dialog B_Child",
                        },
                    },
                RetryPrompt = MessageFactory.Text($"Please choose one of the options."),
            });
    }

    private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        var response = (stepContext.Result as FoundChoice)?.Value.ToLower();

        if (response == "open dialog a_child")
        {
            return await stepContext.BeginDialogAsync(DialogAchildId, cancellationToken: cancellationToken);
        }

        if (response == "open dialog b_child")
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Dialog B_child is not ready need to reprompt previous step."));
            await stepContext.RepromptDialogAsync();
        }

        return await stepContext.NextAsync();
    }

    private static async Task<DialogTurnResult> ContinueStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($"should continue when dialog Achild closed."));
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($""));
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($"will close dialog A."));
        return await stepContext.EndDialogAsync();
    }

    private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        // what is the best way to end this?
        // return await stepContext.ReplaceDialogAsync(InitialId);
        return await stepContext.EndDialogAsync();
    }

最佳答案

your other issue 中指出的问题外,是的,您将正确处理复杂的对话流程。

通过完全按照您正在做的事情来管理复杂的对话流要容易得多:拥有一个主对话类,然后使用 if 语句分支到其他对话中。您可能还想考虑使用 switch 语句,尤其是当您可能在两个以上的方向上分支时。

很好的引用资料

Advanced dialog flow - 一般准则

Creating reusable dialogs - 一般准则

What each method of stepContext does , 与对话有关 - 所以你知道要调用什么来完成你想要的

Prompt Validation Sample - 如有必要,用于集成提示验证

关于c# - 在 Botframework V4 中扩展和链接对话框的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54865737/

相关文章:

C# TransactionScope - L2E

c# - OwinStartup 和在 asp.net mvc 的 signalr 中启动

node.js - 提示不等待用户输入

node.js - 带有 Azure Functions App 和 NodeJS 的 Microsoft Bot Framework

c# - 将列表与具有共同父类(super class)的自定义对象进行比较

c# - 如何使用 oAuth token

c# - DropDownListForModel 无法添加 HTML 属性

node.js - 如何在不同 Node 之间持久保存对话数据?

c# - 表单流的动态返回类型

.net - 使用 Microsoft bot 框架下载文件(pdf/图像)