You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MS Bot Framework:如何取消PromptDialog?PromptDialog.Choice单次取消需求

Got it, let's fix this annoying behavior where users have to type "cancel" three times to exit a PromptDialog.Choice prompt. Here's what's happening and how to fix it:

Why this happens

By default, PromptDialog.Choice treats inputs like "cancel", "quit", or "exit" as invalid choices (since they don't match your listed options). So each time the user types one of these, it counts against your 3 retry attempts instead of immediately exiting the prompt.

Fix 1: Custom Prompt Validator (Bot Framework v4+)

The cleanest solution is to add a custom validator to your ChoicePrompt that intercepts cancel commands first. When detected, we’ll mark the prompt as canceled, which skips the retry loop entirely.

Here’s a working code example in C#:

using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Schema;
using System.Globalization;
using System.Threading.Tasks;

// Define your choice options
var choices = new List<Choice> 
{ 
    new Choice("Option 1"), 
    new Choice("Option 2"), 
    new Choice("Option 3") 
};

// Create a ChoicePrompt with custom validation
var choicePrompt = new ChoicePrompt(CultureInfo.CurrentCulture)
{
    RetryPrompt = MessageFactory.Text("Sorry, that's not a valid option. Try again or type 'cancel' to exit."),
    Validator = async (promptContext, cancellationToken) =>
    {
        var userInput = promptContext.Context.Activity.Text.ToLower();
        
        // Check for cancel commands first
        if (userInput is "cancel" or "quit" or "exit")
        {
            promptContext.Recognized.Status = PromptStatus.Canceled;
            return true; // Mark validation as "passed" to trigger cancel flow
        }

        // Fall back to default choice validation for valid options
        return await ChoicePromptValidator.Validate(promptContext, cancellationToken);
    }
};

// Add the prompt to your dialog set and start it
await stepContext.PromptAsync(
    "choicePrompt",
    new PromptOptions
    {
        Prompt = MessageFactory.Text("Please select an option. Type 'cancel' to exit at any time."),
        Choices = choices
    },
    cancellationToken
);

Later, in your waterfall step handler, you can catch the canceled status to exit gracefully:

var result = await stepContext.ResultAsync<ChoiceResult>();
if (result.Status == PromptStatus.Canceled)
{
    await stepContext.Context.SendActivityAsync("Exiting the prompt as requested.");
    return await stepContext.EndDialogAsync();
}

// Handle valid choice selection here
var selectedOption = result.Value.Value;
await stepContext.Context.SendActivityAsync($"You selected: {selectedOption}");

Fix 2: For Bot Framework v3 (Legacy)

If you’re still using the older PromptDialog.Choice method, you can use a custom validator to intercept cancel commands and handle them in the resume callback:

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

// Launch the choice prompt with custom validation
PromptDialog.Choice(
    context: context,
    resume: AfterChoiceSelection,
    options: new[] { "Option 1", "Option 2", "Option 3" },
    prompt: "Please select an option. Type 'cancel' to exit.",
    retry: "Invalid input. Try again or type 'cancel' to exit.",
    attempts: 3,
    validator: input =>
    {
        var lowerInput = input.ToLower();
        if (lowerInput is "cancel" or "quit" or "exit")
        {
            // Return success with null to signal cancel
            return ValidatorResult.FromSuccess(null);
        }
        // Validate normal choices
        return ValidatorResult.FromSuccess(input);
    }
);

// Handle the prompt result
private async Task AfterChoiceSelection(IDialogContext context, IAwaitable<string> result)
{
    try
    {
        var selection = await result;
        if (selection == null)
        {
            // User canceled the prompt
            await context.PostAsync("Exiting the prompt as requested.");
            context.Done<object>(null);
            return;
        }
        // Handle valid selection
        await context.PostAsync($"You picked: {selection}");
        context.Done(selection);
    }
    catch (TooManyAttemptsException)
    {
        await context.PostAsync("Too many invalid attempts. Exiting prompt.");
        context.Done<object>(null);
    }
}

Bonus User Experience Tip

Always explicitly mention the cancel/quit/exit commands in your prompt messages. This lets users know they have an out without having to guess! For example:

"Please choose an option from the list below. Type 'cancel' at any time to exit this prompt."

内容的提问来源于stack exchange,提问作者Kevin D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:11:13