First, an important note. This content is for Bot Builder SDK v4 which is, at the time of writing this, in pre-release.

In preparing for some upcoming presentations on Creating Bots, I’m upgrading a bot from Bot Builder SDK v3 to v4. It’s new so there isn’t a ton of documentation or samples out there. But if you are building bots for Azure, now is the time to start learning about v4. It’s quite different than the predecessor.

With the old version, you could use the FormFlow feature to easily create “forms” that would gather information needed by the bot to accomplish a task. Consider that if a bot is taking a pizza order, it would need to ask the customer what kind of pizza, what size, find out about side orders and drinks, etc. We had access to the FormBuilder to easily compose a set of prompts to gather the data. Well, in v4, the FormFlow is gone. That’s ok, the new Bot Builder Framework is better Smile.

Again, I am still learning about the new version of the framework and I won’t begin to explain it all here. I found most of the docs very helpful and it was pretty easy to get going. And of course, you can see the source code for the framework on github. However, when it came to providing choices for the user, I couldn’t quite figure it out. I reached out for some help (being a Microsoft MVP has its privileges) and Gary Pretty came to the rescue, pointing me to a sample here. While that sample was helpful, I’ll provide more of an explanation.

So, here is the part about how it works…

The full solution is on github, check it out if you want.

The replacement for the FormFlow is to use a DialogContainer with a list of WaterfallSteps. You can then add a waterfall step for each question you want the user to answer. The questions are asked with the help of a prompt. There are prompts to collect text, numbers, dates, and more. I want to prompt the user to pick an item from a list, so I use the ChoicePrompt. In the constructor of the DialogContainer I have created a prompt:

    var auto = new ChoicePrompt(Culture.English) { Style = ListStyle.Auto };
    Dialogs.Add("auto", auto);

I’ve set the ListStyle to Auto. I’ll get into more detail on that later.

In my constructor I have a list of choices (List<Choice>) and ChoicePromptOptions which wrap the choices and a few other properties including the RetryPromptString.

    var choices = new List<Choice>();
    choices.Add(new Choice { Value = "Plain Pizza", Synonyms = new List<string> { "plain" } });
    choices.Add(new Choice { Value = "Pizza with Pepperoni", Synonyms = new List<string> { "4 Day", "workshop", "full" } });
    choices.Add(new Choice { Value = "Pizza with Mushrooms", Synonyms = new List<string> { "mushroom", "mushrooms", "shrooms" } });
    choices.Add(new Choice { Value = "Pizza with Peppers, Mushrooms and Brocolli", Synonyms = new List<string> { "vegtable", "veggie" } });
    choices.Add(new Choice { Value = "Pizza with Anchovies" });

    _choicePromptOptions = new ChoicePromptOptions { Choices = choices, RetryPromptString = "Sorry, that isn't on the list. Please pick again."};

I also created a WaterFallStep which is really just a method that looks like this:

    private async Task AutoPrompt(DialogContext dc, IDictionary<string, object> args, SkipStepFunction next)
        await dc.Prompt("auto", "What kind of Pizza would you like?", _choicePromptOptions);

Note that here I am telling the DialogContext to show the ChoicePrompt (referring to it by name “auto”), I supply text (“What kind of pizza…”) and the ChoicePromptOptions. This means I can reuse the prompt by providing different text and choices if I want to.

Back in my constructor, I add that waterfall step to my Dialogs collection:

    Dialogs.Add(Id, new WaterfallStep[]

Check it out, it works! Here are some screen shots from the emulator:



More Options

While we are here, let’s get into some other settings.

First there are the list style options:



Prompt Style Samples

I used Auto before, you can see the result above.

Here is a sample using Inline


List looks a lot like auto right? (I think Auto will change depending on the channel for your bot. List is just a list.


As the name suggests, None doesn’t provide any prompts at all.


Lastly, here is SuggestedAction. It provides a list of buttons for the user to click. Depending on your situation this can be a great option.



Also the RetryPromptString allows you to provide text to display if the user enters a value that doesn’t match up to one of the provided options. Note that if you don’t supply a RetryPromptString and in response to the pizza question, a user enters “hot dog”, the bot won’t react well. In my full sample code I have multiple WaterfallSteps and if a user enters an incorrect response, the bot resets the steps and starts from the beginning. Including RetryPromptString let’s the bot ask again and everything works out.

There are other ChoiceOptions for a ChoicePrompt. You can specify if the numbers should be displayed alongside the list items and customize character used to separate the items in the list such as using a comma or pipe.


User Input

The cool part about this is that regardless of which option you use, the user can respond in a variety of ways.

  • For any of these options, the user can simply enter a “3” to indicate “Pizza with Mushrooms”.
  • Users can also input “Pizza with Mushrooms” to select that option.
  • User can also input “mushroom” and get the right selection. That’s because I provided Synonyms for most of the choices. This is a really cool feature.
  • Interestingly, using a number, the text or a synonym all work for the None prompt as well.
  • And Of course, for the SuggestedAction type, users can click the button.

If you want to see all of the code, you can get it on github. I’ve created a sample that includes all of the prompts.




One thought on “Bot Builder SDK: Prompting a user with choices

  1. Pingback: Dew Drop - June 1, 2018 (#2737) - Morning Dew

Leave a reply


<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>