Share via


Microsoft Bot Framework: Getting Started – Understanding Dialogs and Maintaining states between conversations

When end user interacts with Bot a set of conversations is exchanged. This flow of conversation has to be managed. Dialog comes to the rescue here and handles the conversation flow. During these conversations lot of information and data are shared. Bot should be intelligent enough to handle conversation state so that it can retain and use required information across conversations. In this article we will explore the concept of Dialog and how to maintain state in the conversation flows.

Prerequisites

Before deep diving into this article I would strongly recommend you to go through all the previous articles of this series. Here in this article we will not be focusing on the basic concepts of Bot Framework.
Microsoft Bot Framework : Getting Started - Building the first Hello Bot
Microsoft Bot Framework: Getting Started – Making the Bot Intelligent using Text Analytics Sentiment API from Microsoft Cognitive Services
We will concentrate here on Dialogs and State management for the Bot.

Understanding Dialog

Dialog helps in managing flow of conversations between the end user and the Bot. This represents a single session consisting of set of conversations between the end user and the Bot. This starts when the user sends the first message to the Bot incorporating Dialog and ends when it responds back to the last message of the user. Below is an example of a Dialog between end user and the Bot.
http://i.imgur.com/4X4LDE5.jpg
Microsoft Bot Framework provides an interface IDialog. Dialog class needs to implement IDialog interface and implement its method StartAsync to build a Dialog. Dialog can be chained. We will try chaining of Dialogs in the future articles of this series.

Maintaining States between conversations

When the user starts a dialog with the Bot and interacts, series of text messages and information are exchanged. Bot needs to capture the information and maintain the data across conversations in the Dialog. This can be done using UserData class of dialog context. Below are few useful methods of UserData that can be used to manage states during conversations.
SetValue – This is used to set data to the dialog context against a key.
GetValue – This is used to get data from the dialog context for a key.
TryGetValue is a safer alternative to this.

Using Dialog and State Management

Now that we have an idea of Dialog and UserState, let us build a Bot that uses Dialog. Below listed are steps to build this.

Step 1

Open Visual Studio and create a project of type Bot Application.

Step 2

Go to Dialogs folder in the solution and add below InsuranceDialog class.

using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
 
namespace HelloDialogBot.Dialogs
{
    [Serializable]
    public class  InsuranceDialog : IDialog<object>
    {
        public async Task StartAsync(IDialogContext context)
        {
            //Set this flag as true when the user initiates communication with the Bot for the first time. We will maintain the data in the context
            //Bot will not action anything further if this flag is true except sending the welcome message.
            context.UserData.SetValue<bool>("isFirstTextFromUser", true);
            //Send welcome message to user. Ask for user name
            await context.PostAsync(@"Welcome to ""Quick Insurance - World's best Insurance Provider"". May I know your name please. ");
            context.Wait(MessageReceivedAsync);
        }
 
        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
        {
            string insurerName = string.Empty;
            string insuranceID = string.Empty;
            string complaint = string.Empty;
            bool isFirstTextFromUser = false;
            //Gets value of flag isFirstTextFromUser from the context
            context.UserData.TryGetValue<bool>("isFirstTextFromUser", out  isFirstTextFromUser);
            //Gets value of flag insurerName from the context
            context.UserData.TryGetValue<string>("insurerName", out  insurerName);
            //Gets value of flag insuranceID from the context
            context.UserData.TryGetValue<string>("insuranceID", out  insuranceID);
            //Gets value of flag complaint from the context
            context.UserData.TryGetValue<string>("complaint", out  complaint);
            var activity = await result as  Activity;
            //Do not get into this loop if this is the first message from the user. This will avoid setting user's first message 
            //to insurerName
            if (!isFirstTextFromUser)
            {
                //insuranceName is blank corresponds that user is reponding to the Bot's reply - 
                //Welcome to "Quick Insurance - World's best Insurance Provider". May I know your name please.
                //Capture insurerName
                if (string.IsNullOrWhiteSpace(insurerName))
                {
                    //Set insurerName to context
                    context.UserData.SetValue<string>("insurerName", activity.Text);
                    //Prompt user to provide identification number
                    await context.PostAsync("Please provide your insurance identification number");
                }
                //insuranceID is blank and insurerName is not blank corresponds that user is reponding to the Bot's reply - 
                //Please provide your insurance identification number
                //Capture insuranceID
                else if  (string.IsNullOrWhiteSpace(insuranceID))
                {
                    //Set insuranceID to the context
                    context.UserData.SetValue<string>("insuranceID", activity.Text);
                    //Prompt user to provide complaint
                    await context.PostAsync("Let me know your complaint");
                }
                //insuranceID is not blank and insurerName is not blank corresponds that user is reponding to the Bot's reply - 
                //Let me know your complaint
                //Capture complaint text
                else if  (string.IsNullOrWhiteSpace(complaint))
                {
                    //Set complaint to the context
                    context.UserData.SetValue<string>("complaint", activity.Text);
                    //Wrap up
                    await context.PostAsync("Thank you. We have registered your complaint as Name : " + context.UserData.GetValue<string>("insurerName")
                        + ", Insurance ID : "  + context.UserData.GetValue<string>("insuranceID")
                        + ", Complaint : "  + activity.Text + ". Our representative will get back to you shortly. Please end the conversion chat");
                }
            }
            else
            {
                context.UserData.SetValue<bool>("isFirstTextFromUser", false);
            }
            context.Wait(MessageReceivedAsync);
        }
    }
}

Step 3

Go to Controlers\MessagesController.cs and replace Post method with below.

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                //Do converstation with user using InsuranceDialog
                await Conversation.SendAsync(activity, () => new  Dialogs.InsuranceDialog());
            }
            else
            {
                HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }

Step 4

Build the solution and run. The service starts up.
http://i.imgur.com/uLJRbaU.jpg

Step 5

Open Bot framework emulator and communicate with Bot. Below is a sample communication with the Bot we built.
http://i.imgur.com/BZKK3NL.jpg

Source Code

This solution is built using Visual Studio 2017 Community Edition. You can get the source from GitHub repository here.

Next Steps

Below listed are articles that you can check out as next steps.
Microsoft Bot Framework: Getting Started – Sending a File to the Bot
Microsoft Bot Framework: Getting Started – Bot sends an attachment file to the end user