Monday, May 2, 2016

Bot Builder FormFlow

In a previous post on Bot Builder Dialogs, I discussed how you could manage conversations with users. While this wasn’t too hard, consider the amount of complexity involved with a larger conversation. To help simplify the conversation, Bot Builder has another library named FormFlow. In this post, I’ll introduce FormFlow and show you how it can help simplify bot conversations.

What is FormFlow?

FormFlow is a Bot Builder SDK library that lets you declare the type of information you need and then it does the bulk of the work of managing the conversation and moving the user from question to question automatically. In Dialogs, you have the responsibility of writing the methods to prompt the user and collect the results, but FormFlow simplifies the entire process. Another benefit of FormFlow is that it automatically formats questions to be more readable and it tries to process partial answers if it can. Here’s a screen shot of the Bug Report Bot.


To implement FormFlow, define a class with properties and/or methods, decorate the class and members with attributes for customization, and initialize the form when the user communicates with your bot. Because this is only an intro, I’ll limit the scope of the demo to only show how to get FormFlow working and some basic control flow. The demo program is a modification of the Bug Report example from my Bot Builder Dialogs post. The next section explains how to create a form.

Creating a FormFlow Form

As mentioned earlier, a Form is a class with fields and/or properties to hold the information you need. For the Bug Report demo, I just need to know the product, platform, and description, as shown in the following code.

    public class BugReport
        public ProductOptions Product { get; set; }

        public List<PlatformOptions> Platform { get; set; }

        public string ProblemDescription { get; set; }

To properly manage state, your form must be serializable, which is why the BugReport class has a Serializable attribute. The property types are enums, with a member for each valid choice a user could make. Each property holds the value of the choice that the user makes. If the choice type is a List, FormFlow allows the user to enter multiple items for that answer.

One of the benefits of FormFlow is it’s conventions for readable options. e.g. When the bot asks the user for the value it will place into the ProblemDescription property, it will break words by capitalization and print “Problem Description” to the user. Same thing with the enum values.

Configuring the Form

To make the BugReport class a form, instantiate a FormBuilder and tell it the type of form to work with.  Here’s a basic example of how to do that.

        public static IForm<BugReport> BuildForm()
            return new FormBuilder<BugReport>()
                    .Message("Welcome to Bug Report bot!")
                    .OnCompletionAsync(async (context, bugReport) => 
                        await context.PostAsync("Thanks for the report!");

The BuildForm method returns an FormBuilder<BugReport> instance. The FormBuilder gives you a fluent interface, where you can chain several methods together. Message shows a message to the user, which is when the bot starts communicating. There are many methods you could add to this chain to customize the FormFlow conversation and there’s more explanation for those that I won’t cover in this post. FormBuilder will manage the conversation, using the BugReport class.

When the bot finishes, the lambda passed to OnCompletionAsync communicates with the user again. This is where you could take action to do something with the report, like save it in a database or submit to a Web service. The context is the DialogContext, as explained in my Bot Builder Dialogs post and the lambda uses context to send a final message to the user. The lambda’s bugReport parameter holds the BugReport class instance, holding the state that FormFlow collected, which you can use to extract user answers.

I put the BuildForm method inside the BugReport class. The next section shows how to call BuildForm to start bot communication.

Starting the FormFlow Conversation

Now that you have a form (class used as a form) and that form is configured with FormBuilder, you need to start the the conversation. The following example is from the MessageController and shows the flow of control that occurs when the user communicates with your bot.

    public class MessagesController : ApiController
        internal static IDialog<BugReport> MakeRootDialog()
            return Chain.From(() => FormDialog.FromForm(BugReport.BuildForm))

        public async Task<Message> Post([FromBody]Message message)
            return await Conversation.SendAsync(message, MakeRootDialog);

Just as with Dialog conversations, the Post handler method in MessagesController calls Conversation.SendAsync. This argument references a method, MakeRootDialog, to instantiate the dialog. Inside the Chain.From lambda, FormDialog.FromForm references the BuildForm method, from the previous section. It’s saying that as the dialog for this conversation, use the BugReport form.

Chain is interesting in that it has convenience methods for managing forms. This example only uses From and Loop, but there are more that help manage more sophisticated conversations. Loop allows the user to start at the beginning again after the current BugReport form has completed.


Now you’ve seen how FormFlow makes it easy to manage conversations. You create a class with properties, configure that class with a FormBuilder, and create an instance of the FormBuilder when the user communicates with your bot. In addition to knowing how to start the conversation, you also saw how to handle the end of the conversation via the OnCompletionAsync  method.



1 comment:

  1. Quite an impressive post Joe on bot builder form flow you have discussed here.Is there any bot builder platform like Gupshup and chatfuel which helps in easy access use in this form flow