Bot Framework

FormFlow in Bot Framework


I had to create a bot that takes multiple inputs from the user and register the user with the inputs provided. I could  make use of Dialogs in bot framework. Dialogs are very powerful and flexible, But while the user is providing inputs, At each point in the conversation, there are many possibilities of what will happen next. For example, you may need to clarify an ambiguity, provide help, go back, or show progress. The main challenge is to maintain the data until the Conversation is Complete. To overcome these challanges I had to choose formflow over dialogs.  By using FormFlow within the Bot Builder SDK for .NET, you can greatly simplify the process of managing a guided conversation. In this Post I am going to explain how to create a user registration bot  by simply defining the form with a C# class and connecting it to the framework, how can you enable  FormFlow to automatically manage the conversation between bot and user.

Features of a FormFlow

  • Automatically generate and manage the conversation
  • Provide clear guidance and help
  • Understand both numbers and textual entries
  • Provide feedback to the user regarding what is understood and what is not
  • Ask clarifying questions when necessary
  • Allow the user to navigate between steps
  • Extracting the entities from luis and fill in the fields automatically
  • Add Bussiness logic for each and every field.

User Registration Bot

Create the form

To use FormFlow, you must first import the Microsoft.Bot.Builder.FormFlow namespace. The UserRegistration class defines the form. It contains all the fields that are required to register a user. The class also includes the static BuildForm method that uses FormBuilder to create the form and register the user. The FormBuilder gives the flexibility to validate the user Email, concatenate First name and last name to fill username, Validate if username already exists and requests new user name if the user name is already taken. It also prompts a confirmation message once the user completes the form.

public class UserRegistration
    [Prompt("PLEASE ENTER FIRSTNAME!.. {||}")]
    public string FirstName;
    [Prompt("PLEASE ENTER LASTNAME!.. {||}")]
    public string LastName;
    [Prompt("Please enter Email Id!.. {||}")]
    public string Email;
    [Prompt("PLEASE ENTER USERNAME!.. {||}")]
    public string Username;

    public static IForm<UserRegistration> BuildForm()
        OnCompletionAsyncDelegate<UserRegistration> RegisterUser = async (context, state) =>
            StringBuilder message = new StringBuilder();
            var res = RegisterUser(state.FirstName, state.LastName, state
            .Email, state.Username);
            await context.PostAsync(message.ToString().ToUpper());
        var form = new FormBuilder<UserRegistration>()
        validate: async (state, value) =>
            state.Username = state.FirstName + state.LastName;
            var exists = CheckIfValidEmail((string)value);
            return new ValidateResult { IsValid = exists, Value = value, Feedback = !exists ? $"Please enter a valid email." : null };
        validate: async (state, value) =>
            var exists = CheckIfUserExists((string)value);

            return new ValidateResult { IsValid = !exists, Value = value, Feedback = exists ? $"Username {value} is already taken. Please take another user name" : $"Lucky you! Username {value} is available!" };
        .Confirm("**Are you sure you want to add a user with first name {FirstName} lastname {LastName} and email id {Email}**");

        form.Configuration.DefaultPrompt.ChoiceStyle = ChoiceStyleOptions.Buttons;

        return form.Build();


Connect the form to the framework

To connect the form to the framework, you must add it to the controller. In this example, the Conversation.SendAsync method calls the static MakeRootDialog method, which in turn, calls the FormDialog.FromForm method to create the UserRegistration Form

internal static IDialog<UserRegistration> MakeRootDialog()
    return Chain.From(() => FormDialog.FromForm(UserRegistration.BuildForm));

public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
    if (activity != null)
        switch (activity.GetActivityType())
            case ActivityTypes.Message:
                await Conversation.SendAsync(activity, MakeRootDialog);

            case ActivityTypes.ConversationUpdate:
            case ActivityTypes.ContactRelationUpdate:
            case ActivityTypes.Typing:
            case ActivityTypes.DeleteUserData:
                Trace.TraceError($"Unknown activity type ignored: {activity.GetActivityType()}");

You Can also connect the form from a method in LUIS Dialog and fill in the form fields with  the Luis entities

public async Task RegisterUser(IDialogContext context, LuisResult result)

    EntityRecommendation EmailId;

    result.TryFindEntity("", out EmailId);

    var model = new UserRegistration();

    if (EmailId != null)
        model.Email = EmailId.Entity;
    var RegisterUserForm = new FormDialog<UserRegistration>(model, UserRegistration.BuildForm, FormOptions.PromptInStart);
    context.Call(RegisterUserForm, RegisterUser_Callback);

user registration in action

Able to extract email id from luis and fill in automatically

Validating the username with buissiness logic

Automatically filling in the user name by concatinating firstname and last name and making sure that user name is available

You can modify the inputs before submission

At any point of conversation you can know the status of the form

About The Author

Leave a Reply