Create Azure Bot Service from Scratch using Empty Asp.Net Core

To create a new Azure Bot Service Project, you can use the easy way by utilising the Azure Bot Service SDK Templates which you can download here. You will also need the Bot Service SDK which is a list of nuget packages. Current version is 4

Once you downloaded the bot template, installed it, you should find a new project template in visual studio. You can choose a project name, click Ok and you will end up with an echo bot that repeats what you say.

Visual Studio project

But this isn’t fun. In this post, I will create an empty asp.net project and add the needed boilerplate to make it a bot. Lets get started

Open Visual Studio (I am using VS 2019 Preview 2). CLick New Project, select Asp.net Core Web Application, name is HelloAzureBot and Choose Empty as the project template. Then click Ok

Adding reference to Bot Service SDK

To enable bot service in our asp.net core web app, we will need to add reference to the Bot SDK packages. We need the following packages:

  • Microsoft.Bot.Builder
  • Microsoft.Bot.Builder.Integration.AspNet.Core
  • Microsoft.Bot.Configuration
  • Microsoft.Bot.Connector
  • Microsoft.Bot.Schema

You can add it via NuGet Package manager Console, Manage NuGet Packages dialog or you just edit the project file and add the following to it:


<PackageReference Include="Microsoft.Bot.Builder" Version="4.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.2.2" />
<PackageReference Include="Microsoft.Bot.Configuration" Version="4.2.2" />
<PackageReference Include="Microsoft.Bot.Connector" Version="4.2.2" />
<PackageReference Include="Microsoft.Bot.Schema" Version="4.2.2" />

Your project file should look like this now:

Injecting Bot Service in Asp.Net Core

Now, lets inject the Bot Service into asp.net core middleware. This will basically create an endpoint that will accept post requests sent to /api/messages .
Open startup.cs file and in Configure method, add the following line. Don’t forget to remove the default middleware that print hello world.

app.UseBotFramework();

Now, our solution is ready to create a new Bot.
Create a new class and name it EchoBot. Make it inherits from IBot interface and implement the OnTurnAsync. This is the method that get called when its your bot’s turn to speak to the user.

    public class EchoBot : IBot
    {
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            await turnContext.SendActivityAsync($"Hi, You said: {turnContext.Activity.Text}");
        }
    }

This is a very simple bot that does nothing but echo what you say. To send a message to the user, we use the TurnContext.SendActivtyAsync. Note that activity is any thing (message, voice, card ..) going between the user and the bot.

Tell Bot service about your Bot

Now, your project is ready except that it does not know about your Bot.We injected the Bot Service in the asp.net core middleware but we didn’t tell it about the echo bot. Its the same process as configuring MVC in Configure method but we have to also inject it a service in the ConfigureServices method. Now open startup.cs file again and edit the ConfigureServices method to match the following:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddBot<EchoBot>();
        }

Testing the Echo Bot

The bot is ready now to accept chat requests. Press F5 to run your project. It will open the browser with a new windows that tells you that no page can be found. This is normal as we didn’t inject any middleware to handle the root URL. In the SDK template, it uses static HTML file under wwwroot that has an introduction to the service. But this is not mandatory.

To test the bot, we will need a channel to talk to it. Microsoft released the bot emulator for that purpose. It allows you to connect and chat with your bot without deploying it to Azure Bot Service. The current emulator version is 4. But for some reason, it just does not work with me for local bots. It needs the bot to be deployed to Azure or at least create an Azure Bot Service and configure the Bot URL to be your local bot. You will expose the bot to Azure using ngrok. Another option is to just use Emulator V3 which you can easily provide the Bot URL which takes the format http://localhost:PORT/api/messages.

Bot Emulator

Download the Bot Emulator V3 from here and install it then run it. On the top, add the URL for your Bot in the format mentioned before and hit enter. Start playing around and enter any message and you should receive the reply with: Hi, You said: YOUR_MESSAGE.

You will notice that you will immediately receive the messages: “Hi, You said: and Hi, You said:” just after you entered the Bot URL. This is because the OnTurnAsync method is called when the user joins and when the bot joins or when you send a message. To filter, you have to add the following to your OnTurnAsync method

        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                await turnContext.SendActivityAsync($"Hi, You said: {turnContext.Activity.Text}");
            }
        }

You can check if the activity type is ActivityTypes.ConversationUpdate and then check the turnContext.Activity.MembersAdded property and use that to send a message to welcome the new members. ex: John has joined the conversation.

Handling Errors

When your bot encounters an issue or unhandled exception, you can catch that exception through an error handler. You can configure that in the ConfigureServices method when you call the AddBot method. The Startup.cs should be as below. We utilise the OnTurnError handler to send a message to the user informing him/her that something went wrong and log the exception.

 public class Startup
    {
        public ILoggerFactory LoggerFactory { get; }

        public Startup( ILoggerFactory loggerFactory)
        {
            this.LoggerFactory = loggerFactory;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddBot<EchoBot>(options =>
            {
                // Creates a logger for the application to use.
                ILogger logger = this.LoggerFactory.CreateLogger<EchoBot>();

                // Catches any errors that occur during a conversation turn and logs them.
                options.OnTurnError = async (context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseBotFramework();
        }
    }

.Bot File

The emulator that comes with SDK V4 uses a .bot file that describes the bot, the services that the bot uses and the URL where it runs.
A typical .bot file contains the following:

{
  "name": "HelloAzureBot",
  "services": [
    {
      "type": "endpoint",
      "name": "development",
      "endpoint": "https://localhost:44331/api/messages",
      "appId": "",
      "appPassword": "",
      "id": "1"
    }
  ],
  "padlock": "",
  "version": "2.0"
}

The content of the file is self explanatory but the most important details are the name and endpoint. This is what tells the Emulator how to reach your bot.
If the bot is deployed on Azure Bot Service, you will need to provide the appId and appPassword

That will be the end of our post. In the next post, we will talk about the state management. If you didn’t read the previous post, please do.