本文介绍了BotFramework V4:RepromptDialogAsync不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法使RepromptDialogAsync()正常工作.我是这样做的.选择对话框b时,应重新提示选择提示,因为对话框B尚未准备好.但是,选择对话框它什么都不做的时候.我做错了吗?我在文档上找不到任何RepromptDialogAsync()教程.谢谢!

I can't make RepromptDialogAsync() to work. I am doing it like this. 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. Am I doing it wrong? I can't find any RepromptDialogAsync() tutorial on docs. Thank you!

主要代码:

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();
    }

推荐答案

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

I'll address a couple of issues in this answer:

RepromptDialogAsync() 在当前活动的对话框上调用reprompt,但应与具有reprompt行为的提示一起使用. ChoicePrompt确实具有reprompt选项,但并不打算在此上下文中使用.取而代之的是,您将调用提示符,在OnTurnAsync中验证响应,然后根据需要调用dc.RepromptDialogAsync().

RepromptDialogAsync() calls reprompt on the currently active dialog, but is meant to be used with Prompts that have a reprompt behavior. ChoicePrompt does have a reprompt option, but isn't meant to be used in this context. Instead, you'd call your prompt, validate the response within OnTurnAsync, and call dc.RepromptDialogAsync() as necessary.

您的OnTurnAsync可能看起来像这样:

Your OnTurnAsync might look something like this:

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()用于您的用例.而是使用以下选项之一:

That being said, I wouldn't use RepromptDialogAsync() for your use case, at all. Instead, use one of the following options:

最简单的选择是替换:

await stepContext.RepromptDialogAsync();

具有:

return await stepContext.ReplaceDialogAsync(InitialId);

这将重新启动您的"mainDialog".在您的示例中,这很好,因为您是从第二步重新回到第一步.

This starts your "mainDialog" over. In your example, this is fine, because you're restarting from the 2nd step back to the first.

ChoicePrompt自动验证用户是否使用有效选项进行响应,但是您可以传递自己的自定义验证器.像这样:

ChoicePrompt automatically validates whether or not the user responds with a valid option, but you can pass in your own custom validator. Something like:

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".相反,您可以执行以下操作:

Other Issues

Really, though, you shouldn't prompt your user with the option to select "dialog b" if it isn't ready. You could, instead, do something like:

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

这篇关于BotFramework V4:RepromptDialogAsync不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 05:08