Search code examples
c#botframeworkbotsprompt

Bot Framework: Prompt and retry prompt messages appear at the same time


I have a prompt that I'm displaying to the user that contains a prompt message and retry prompt message, see below:

return await ctx.PromptAsync(CancelCurrentDialogsPrompt, new PromptOptions
{
    Prompt = MessageFactory.Text("Are you sure you'd like to cancel?"),
    Choices = ChoiceFactory.ToChoices(confirmationOptionsList),
    RetryPrompt = MessageFactory.Text("Please select or type yes/no")
}, cancellationToken);

When I run the BOT in the emulator, the prompt message and the retry prompt message appear at the same time, which I'm not expecting to happen, see below:

Multiple prompts

When I enter in a incorrect option, the retry prompt shows as expected. After selecting a correct value from the list the conversation continues as expected, with no incorrect dialogs.

--- UPDATE ---

I'm calling the cancel dialog using the following code from my bot.cs class

await dialogContext.BeginDialogAsync(nameof(CancelDialog));

When it is being called there is nothing on the dialog stack. Here is the code in my CancelDialog.cs

public class CancelDialog : ComponentDialog
    {
        public readonly BotDialogSet DialogSet;

        private const string CancelWaterfallDialogs = "CancelWaterfallDialogs";
        private const string CancelCurrentDialogsPrompt = "CancelCurrentDialogsPrompt";

        public CancelDialog(BotDialogSet dialogSet) : base(nameof(CancelDialog))
        {
            DialogSet = dialogSet;

            var waterfallSteps = new WaterfallStep[]
            {
                WouldYouLikeToCancel,
                CompleteUsersSelectedAction
            };

            AddDialog(new WaterfallDialog(CancelWaterfallDialogs, waterfallSteps));
            AddDialog(new ConfirmPrompt(CancelCurrentDialogsPrompt));
        }

        private static async Task<DialogTurnResult> WouldYouLikeToCancel (WaterfallStepContext ctx, CancellationToken cancellationToken)
        {
            return await ctx.PromptAsync(CancelCurrentDialogsPrompt, new PromptOptions
            {
                Prompt = MessageFactory.Text("Are you sure you'd like to cancel?"),
                RetryPrompt = MessageFactory.Text("Are you sure you'd like to cancel? Please select or type yes/no")
            }, cancellationToken);
        }

        private static async Task<DialogTurnResult> CompleteUsersSelectedAction(WaterfallStepContext ctx, CancellationToken cancellationToken)
        {
            if ((bool)ctx.Result)
            {
                await ctx.Parent.CancelAllDialogsAsync(cancellationToken);
                return await ctx.EndBotDialogAsync(cancellationToken);
            }

            return await ctx.EndDialogAsync(cancellationToken: cancellationToken);
        }
    }

Solution

  • 1- define the following:

     AddDialog(new TextPrompt("YNValidator", YesNoValidator);
    

    -add it after:

      AddDialog(new ConfirmPrompt(CancelCurrentDialogsPrompt));
    

    2- define YesOrNValidator:

    private Task<bool>YorNValidator (PromptValidatorContext<string> promptContext, CancellationToken cancellationToken)
    {
      //Test the value... and pass true or false
        Task.FromResult(true);
     }
    

    3- Next REWRITE the WouldYouLikeToCancel

    private static async Task<DialogTurnResult> WouldYouLikeToCancel (WaterfallStepContext ctx, CancellationToken cancellationToken)
        {
            var options= new PromptOptions
            {
                Prompt = MessageFactory.Text("Are you sure you'd like to cancel?"),
                RetryPrompt = MessageFactory.Text("Are you sure you'd like to cancel? Please select or type yes/no")
            }, cancellationToken);
        return await stepContext.PromptAsync("YNValidator",options,cancellationToken);
        }