Creating your first bot with the Microsoft Bot Framework

Introduction

This post is actually my second on getting started with the bot framework. I’m starting again as Microsoft has provided significant updates to the bot framework with V3 and some things are now done in a different way. I will be posting several tutorials over the coming days which will take you from the basics and onto more advanced topics. Today we will just look at creating a bot with a simple dialog.

Create the project

To create a bot application you should install the Visual Studio template from here. For my example I have taken a basic solution which contained a project called FootballData. This project is just used for simple demonstrations and gives us something to allow our bot to get data in response to our input.

Create your dialog

When you first create bot project you get some sample code in the MessageController class. Rather than use this we are going to create our own Dialog. To do this you create a new class in the root of the project. I am going to call mine ChampionshipDialog. This class needs to implement IDialog and also to be marked as serializable. At this stage the dialog should look similar to this. (if you have Visual Studio generate the methods for the interface it wont mark as async, but it will be needed later so its worth adding it now.)

[Serializable]
public class ChampionshipsDialog : IDialog
{
    public async Task StartAsync(IDialogContext context)
    {

    }
}

When our Dialog is first created the StartAsync method will be called. Here we need to wait for a message from the user. Additionally what we are going to want to do is carry out an action based on the users input, and ensure that we can still listen out for more messages.

public static Championships champs;
        
public async Task StartAsync(IDialogContext context)
{
    champs = new Championships();
    context.Wait(MessageReceivedAsync);
}

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var msg = await result as Activity;
    //we will carry out our actions here

    context.Wait(MessageReceivedAsync)
}

In the code above all we have done is call MessageReceivedAsync and then get the Activity object from the bot. The Activity is where we will get the text entered by the user. In earlier versions of the bot framework the result would be of a type Message, this changed in v3 and the Activity could be of various types. In our application we are only going to call this Dialog if the Activity is of the type Message, but that will be covered in the next section. The other thing I have done is at the end of MessageReceivedAsync I have told the context to wait for further input. This ensures that our bot keeps listening and doesn’t just shut down after the first message.

Now we are in a position to add some functionality to our Dialog. First of all, we are just going to see if the text sent to the bot contains “how many teams”. If this is the message we can then call the appropriate method in our Championships class and then post back to the user the result.

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var msg = await result as Activity;
    if (msg.Text.Contains("how many teams"))
    {
      await context.PostAsync($"There are { champs.GetTeamCount() } teams in the championships.");
    }
    context.Wait(MessageReceivedAsync)
}

Just providing simple answers like that is not really much use, so what we can now add cases to respond to different questions/statements from our users. So now we go through and interpret the message and carry out actions accordingly. A more complete example is shown below.

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var msg = await result as Activity;
    if (msg.Text.Contains("how many teams"))
    {
       await context.PostAsync($"There are { champs.GetTeamCount() } teams in the championships.");
    }
    else if (msg.Text.StartsWith("who") || msg.Text.StartsWith("which"))
    {
       if (msg.Text.Contains("best") || msg.Text.Contains("top") || msg.Text.Contains("greatest"))
       {
          await context.PostAsync($"The top rated team is { champs.GetHighestRatedTeam() }");
       }
       else if (msg.Text.Contains("worst") || msg.Text.Contains("bottom") || msg.Text.Contains("lowest"))
       {
          await context.PostAsync($"The lowest rated team is { champs.GetLowestRatedTeam() }");
       }
       else
       {
          await context.PostAsync("Sorry I didnt understand the question.");
       }
    }
    else if (msg.Text.StartsWith("remove"))
    {
       string team = msg.Text.Replace("remove", "").Trim();
       try
       {
          champs.RemoveTeam(team);
          await context.PostAsync($"The team { team } has been removed from the championships.");
       }
       catch (TeamNotFoundException)
       {
          await context.PostAsync($"The team { team } was not found.");
       }
    }
    else
    {
       await context.PostAsync("Sorry I didnt understand the question.");
    }
    context.Wait(MessageReceivedAsync);
}

Don’t be too worried about the what I’m calling in the Championships class, the important thing is to look at the structure of the dialog. There are a couple of things here that I would like to point out. The first is that at the end I have added a final else statement for we don’t get any recognised input. It is important to always send a response back to the user, even if it is just to tell them that you have no idea what they are asking. The second is that we are having to a lot of checking what text says and even having or statements to allow for users using different phrases. This can add up to a lot of time trying to work out how users will ask a question. We can improve this by using a natural language service such as LUIS. Which my next post will be covering.

Wire things together

For now lets connect our dialog to our bot. If we go back to the MessagesController class and in the Post method, replace everything within the if statement for ActivityTypes.Message with the statement

await Conversation.SendAsync(activity, () => new ChampionshipsDialog());

This statement is telling the bot to use our new Dialog. The full code looks similar to this:

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

Test in the emulator

If we debug the bot service now and open up the bot emulator that can be downloaded from here. We can communicate and get the results expected. We now have our simple bot up and running.

Emulator

What next

The code in this post is a simplistic view of a bot. We haven’t covered prompts to the user to confirm an action, holding state, multiple users or many other features. I will be blogging regularly on bots and will be going through many of the more advanced features, so you can subscribe or keep checking back here for more info. The Microsoft site dev.botframework.com has some great information as well.

Author: Dave Green

Software developer focusing on Microsoft Technologies, MCSD in Windows Store Apps, full time developer at a real job, part time writer and terrible golf player. Follow on twitter @IntelligentLabs

Leave a Reply

Your email address will not be published. Required fields are marked *