【问题标题】:BotFramework V4: RepromptDialogAsync not workingBotFramework V4:RepromptDialogAsync 不起作用
【发布时间】:2019-02-24 08:04:10
【问题描述】:

我无法让RepromptDialogAsync() 工作。我正在这样做。 When dialog b is chosen it should re-prompt the choice prompt because dialog B is not yet ready. But when choosing dialog b it is doing nothing.我做错了吗?我在文档上找不到任何 RepromptDialogAsync() 教程。谢谢!

主代码:

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,
            ThirdStepAsync,
            FourthStepAsync
         };
        AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
        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")
        {
            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))
    {
       // do something else
        return await stepContext.NextAsync();
    }

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

【问题讨论】:

标签: c# botframework


【解决方案1】:

我将在这个答案中解决几个问题:

回答您的实际问题

RepromptDialogAsync()calls reprompt on the currently active dialog, but is meant to be used with Prompts that have a reprompt behaviorChoicePrompt 确实有一个 reprompt 选项,但并不打算在这种情况下使用。相反,您会调用提示符,验证 OnTurnAsync 中的响应,并根据需要调用 dc.RepromptDialogAsync()

您的OnTurnAsync 可能如下所示:

public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    var activity = turnContext.Activity;

    var dc = await Dialogs.CreateContextAsync(turnContext);

    if (activity.Type == ActivityTypes.Message)
    {
        if (activity.Text.ToLower() == "open dialog b")
        {
            await dc.RepromptDialogAsync();
        };
...

话虽如此,我根本不会将RepromptDialogAsync() 用于您的用例。相反,请使用以下选项之一:

1。 ReplaceDialogAsync()

对您来说最简单的选择是替换:

await stepContext.RepromptDialogAsync();

与:

return await stepContext.ReplaceDialogAsync(InitialId);

这将重新启动您的“mainDialog”。在您的示例中,这很好,因为您从第二步重新开始回到第一步。

2。提示验证

ChoicePrompt 自动验证用户是否使用有效选项进行响应,但您可以传入自己的自定义验证器。比如:

AddDialog(new ChoicePrompt(choicePrompt, ValidateChoice));
...
private async Task<bool> ValidateChoice(PromptValidatorContext<FoundChoice> promptContext, CancellationToken cancellationToken)
{
    if (promptContext.Recognized.Value.Value.ToLower() == "open dialog b")
    {
        return false;
    }
    else
    {
        return true;
    }
}

其他问题

不过,实际上,如果“对话框 b”尚未准备好,您不应该提示用户选择选择“对话框 b”。相反,您可以执行以下操作:

var choices = new List<Choice>
        {
            new Choice
            {
                Value = "Open Dialog A",
            }
        };
if (bIsReady)
{
    choices.Add(new Choice
    {
        Value = "Open Dialog B",
    });
};

【讨论】:

  • 谢谢你,先生,如果它没有准备好,我会考虑你的建议不要包括它。这是因为我希望用户知道该功能将来会可用。重新启动对话框有点烦人,因为在我的真实对话框中,提示位于对话框的中间,所以重新启动它是一种很长的路要再次到达提示。验证器不会发回选择,但这正是我想要的。
  • 我不知道如何在OnTurnAsync 的其他课程中验证我的提示。楼主能教我怎么做吗? “相反,你会调用你的提示,验证 OnTurnAsync 中的响应,并根据需要调用 dc.RepromptDialogAsync()”
  • 你是什么意思,“验证器不发送回选择”?我已经编辑了我的答案以包含OnTurnAsync 的代码,尽管我真的建议使用提示验证(我的答案中的#2)。
  • 谢谢先生。我认为我会坚持你的建议,重新启动对话或包含一个验证器。谢谢楼主!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
相关资源
最近更新 更多