A practical guide to building a Bot using Microsoft Bot Framework using C# and host it in Azure, and use it with Microsoft Teams, Skype and more

Tobias Zimmergren
Tobias Zimmergren

1. Introduction

In this post we'll explore how easy it is to actually build a bot for Microsoft Teams using the Microsoft Bot Framework, which can be found here https://dev.botframework.com.

This post is meant as a starting point for building bots and conversational helpers using the Microsoft Bot Framwork. Of course, it doesn't have to be limited to the Microsoft Teams channel, it can be targeting Slack, Skype or any other available distribution channel.

For the sake of this post, I'll show how to build it and use it with Teams initially.

1.1 The bot: Nerdibot

As the title of the bot might subtly suggest, it's a bot that replies with nerdy quotes. Very basic.

I even created a nerdibot logo using Paint 3D on my Windows 10 laptop.

nerdibot logo

1.2 Pre-requisites

A few things you'll require are:

  • Visual Studio 2017 is my preferred editor today
  • Azure Subscription

2. Creating the boilerplate for the Microsoft Bot Framework in Azure and source control

In order to get started with building a successful bot using the Bot Framework, we should register it in the dev portal (https://dev.botframework.com).

2.1 Start registration of our new Bot in the Microsoft Bot Framework dev portal

Sign in to the dev portal, then head on over here:

Register your Microsoft Bot Framework bot

There's currently only one option to select, so the obvious action is to click Create.

Next, we have to select where this bot will run. Do we build a completely new bot and host it in Azure or do we already have a bot running and we just want to register it?

Well, for the sake of this post we're going with option number 1; Create a new SDK bot hosted in Microsoft Azure.

Select to build a bot hosted in Azure

This will take us to the Azure Portal, ready to create a new Bot Service (preview) - pretty convenient:

2.2 Create resources in Azure to host our Bot

Create your bot in Azure by populating the details you want for your bot

Once it's finished, you'll see a notification in the portal:

Azure notification indicating that the resources were successfully deployed

Click the button Go to resource to visit your new Bot resource in Azure, and we can get started with the fun part.

Select the template you'd like for your bot. Again, for the demonstration of this guide I'm using the C# template and using the most basic version of a bot template available, Basic. We can extend the logic of this to infinity later, should we want to make it a bit more amazing.

Microsoft Bot Framework template selection in Azure

Click Next at the bottom of the page.

2.3 Create a Microsoft App ID for your new bot

You'll be seeing the following page, where you will need to click Create Microsoft App ID and password:

Create Microsoft App ID and Password

Clicking the button will take you to the Application Registration Portal, from which you'll be able to generate your Application Id and Password:

Application Registration Portal - App Id and Password generated

Click Finish and go back to Bot Framework.

Ensure that the App Id is correctly entered by default (it will be), and ensure you paste the password you securely copied in the previous step:

Enter AppId and Password into the registration page in Azure

2.4 Connect to GitHub

So, this is obviously an optional step. You can select to hook it up to continuous deployment, or not. I think it's pretty sweet as it gives us continuous deployments. I'm using https://github.com for this.

Enter your GitHub (or other source control provider) credentials:

Connect to GitHub for easy continuous deployment

It will automatically connect to GitHub now, and create a new repository with the name of your bot. Mine ended up with https://github.com/Zimmergren/nerdibot

Configure continuous deployment by following the config button.

I'm happy with the default settings for now.

On GitHub, I can see the repo successfully being created:

GitHub repository created, and initial source code has been deployed

3. Tips for testing the bot

Great, we've set things up and we're ready to go. Code is deployed using CD and GitHub, and the template code has been deployed.

How do I test this thing, to ensure it actually does something I want?

3.1 Test the bot from the Azure Portal

From inside the Azure Portal, we can easily test the bot functionality using the big blue Test button. The functionality of the current bot is simple: Echo whatever you type. That's the basic demo we selected initially.

Test Button in Azure Portal

Okay, we can see that things work. But it's not really convenient to try and troubleshoot anything at all from here.

3.2 Use the Microsoft Bot Framework Emulator (recommended)

3.2.1 Connect to the Cloud-hosted version of the bot when it's deployed

Sometimes it's beneficial to inspect the requests and responses from a service that's deployed and already running. Since our bot is published publically and available already (from the previous steps), we should be able to reach the Bot on the Url we specified when configuring it in Azure.

My bot exists at https://nerdibot.azurewebsites.net.

Download the Bot Framework Emulator and install it.

Installing Microsoft Bot Framework Emulator

Since we're also connecting to a service hosted outside of the firewalls and routers (which I assume everyone has, right?), we need to tunnel the request back to our machine. Using ngrok we can easily do this, and it's fluent with the emulator.

Head on over to https://ngrok.com and download it.

Download ngrok

Put the executable where you want it, as long as you remember it in the next step.

Launch Bot Framework Emulator and click the three vertical dots (ellipsis menu) and select App Settings:

Emulator App Settings to configure ngrok

Ensure the path to the ngrok.exe executable is entered correctly, select to bypass for local addresses (normally it doesn't make sense to use it when debugging localhost later..), click Save.

Now it's time to try and connect to our hosted bot. Enter the URL to your bot, followed by /api/messages (see the routes in the source code if you're wondering where this comes from).:

Bot Framework emulator about to connect to the cloud

Hit Connect!

BOOM! We can now connect to our remote bot from the emulator, using our App Id and Secret as we entered in the previous dialogue.

Bot Framework Emulator connected to the remote bot we created

We'll see the logs of what goes on through the emulator, helping us troubleshoot any issues we might have.

3.2.2 Connect and debug on localhost during development

Great - we've created a bot, we've put it in the cloud and we've verified that it works both in the Azure Portal and using the Desktop application Bot Emulator.

Now we want to debug it while running on localhost.

  • Clone your GitHub repository (if you're using that source control option)
  • Launch the Solution which by default is called Microsoft.Bot.Sample.SimpleEchoBot.sln
  • Hit F5 without modifying any of the code

We can see that a browser is launching and hitting the localhost Url, in my case it lands on https://localhost3984.

  • Copy this Url and append the same /api/messages as when doing it remotely
  • Enter the full Url into the Bot Emulator now and test it

Bot Framework emulator working on localhost bots

4. Developing your bot

We'll be changing a bit of the code of the bot to ensure that it works, our continuous deployment works, and that the hosted version of our bot gets the updates.

While a different post will cover the more in-depth aspects of the actual bot development (there's some gotchas and a lot of fun tips), we'll focus on the steps required for getting things to work here.

4.1 Introducing a Chuck Norris API call and utilizing the IActivity to return a "Bot is typing" type of message

I've changed the code in the main EchoDialog which is given to us by default. I've introduced a Chuck Norris API which gives you a reply with a quote as if it were Chuck, and added an IActivity implementation sending back a message to the client that the bot is "Nerdibot is thinking..". The reason for this activity is that you can then see in the UI that the bot has received your request, and it's working on a reply - for example if the API call takes a bit longer or if it needs to do more complex queries or computing, it might be a good idea to indicate to the user that it's working on it.

Here's the full code of the EchoDialog now, with the small changes to introduce the two above things:

using System;
using System.Threading.Tasks;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.Dialogs;
using System.Net.Http;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace Microsoft.Bot.Sample.SimpleEchoBot
    public class EchoDialog : IDialog<object>
        public async Task StartAsync(IDialogContext context)

        public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
            #region Is Typing Activity

            var activity = context.Activity as Activity;
            Trace.TraceInformation($"Type={activity.Type} Text={activity.Text}");
            if (activity.Type == ActivityTypes.Message)
                var connector = new ConnectorClient(new System.Uri(activity.ServiceUrl));
                var isTyping = activity.CreateReply("Nerdibot is thinking...");
                isTyping.Type = ActivityTypes.Typing;
                await connector.Conversations.ReplyToActivityAsync(isTyping);

                // DEMO: I've added this for demonstration purposes, so we have time to see the "Is Typing" integration in the UI. Else the bot is too quick for us :)


            #region Handle incoming message

            var message = await argument;

            HttpClient client = new HttpClient();
            var chuckJoke = client.GetStringAsync("https://api.chucknorris.io/jokes/random").Result;

            var deserializedChuck = JsonConvert.DeserializeObject<dynamic>(chuckJoke);
            string chuckSays = ((dynamic) deserializedChuck).value.ToString();

            await context.PostAsync(GetRandomGreet(activity.From.Name) + Environment.NewLine + chuckSays);



        private string GetRandomGreet(string name)
            List<string> greetings = new List<string>
                $"Hey there {name}!",
                $"Okay {name}.",
                $"{name}, your request has been considered, and I approve. This time.",
                $"Okidoki {name}.",
                $"What's up my awesome pal, {name}."

            Random r = new Random();
            int index = r.Next(greetings.Count);
            string randomString = greetings[index];

            return randomString;


When running the bot, it will now look something like this:

  1. When you type something to the bot:

Typing to the bot, it will reply with an indicator that its working on it

Once the message is handled and the bot finished thinking (e.g. my dummy Thread.Sleep() elapsed), you should see the reply:

Bot Framework in action, showing the reply of Chuck Norris

5. Connect the bot to various channels

Right, now imagine you've got all your awesome code up and running, and your bot is doing what ever it is that you need it to do. We need to distribute it across various channels and try it out with various platforms.

In order to try it out with a real platform, instead of just the Bot Framework Emulator and Azure test UI, we'll try to add it to a few different channels. Tag along.

5.1 Add your bot to Skype (consumer)

We'll be connecting to Skype first. It's already running by default and we'll be tring that out.

  1. Head over to the Bot dev portal again at https://dev.botframework.com
  2. Click on the Skype channel which should be connected already:

Skype channel for connecting to the bot

  1. Add the bot as a contact so you can communicate with it

Add the nerdibot as a contact

  1. In your Skype client, you can now see your new bot as a contact

Your new bot is now a contact in Skype

  1. Chat with the bot!

Chat with your new chatbot in Skype consumer

  1. We'll see that it's got the delay in place (is typing...) and it gets my name correct

Bot is replying

My bot is live on Skype, and can be found here:

5.2 Integrate your bot with any web form

Another standard feature of the Microsoft Bot Framework is to host your bot on any web site or form of your choosing. This is an interesting option if you're integrating a support bot or helper bot on your publish website (or even on your intranet).

  1. Head over to the Bot dev portal again at https://dev.botframework.com
  2. Click on the Edit link next to the Web Chat channel:

Connect web chat for your bot

  1. Make a note of ( 1 ) the Secret Key
  2. Make a note of ( 2 ) the Embed Code
  3. Click Done

Embed Code

  1. Copy the Secret into the Embed Code and replace the YOUR_SECRET_HERE with your own secret
  2. Copy this embed code into any web site of your choice

Here's what my embed code looks like (I've faked the Secret to avoid abuse):

<iframe src='https://webchat.botframework.com/embed/nerdibot?s=nVaFe_v6dfdfwA.tMg.dfdfzoFWruRrQb_WqJSJEwP0qIY7c8dfdfcvRZ8k' width="500px" height="800px"></iframe>
  1. I copied this embed code into hello.html which contains nothing else

See the web form of your bot in action, and it works

Awesome, we've connected it to a website as well. Obviously, you may want to connect it to an actual web site for a more realistic use case, but now you know how to do that.

5.3 Connect your bot to Microsoft Teams

  1. Head over to the Bot dev portal again at https://dev.botframework.com
  2. Click on your bot
  3. Click on the Microsoft Teams logo to add a new channel

Add Microsoft Teams to your bot channels

  1. It will tell you that it's connecting to Teams, hit Done

Acknowledge the connection to Teams

  1. Click the newly connected Teams channel and it will, just like with for Skype, launch the browser to connect to Teams with your new bot

Click the teams channel

  1. You're connected to the chatbot in your Teams tenant, but he doesn't reply. Why?

No reply from the bot

This is due to Microsoft Teams not being configured for Side-loading any apps.

Please read here: https://docs.microsoft.com/en-gb/microsoftteams/platform/get-started/get-started for how to configure sideloading.

Please note: If you don't sideload your app, it will not be able to communicate. Unless you publish the bot, in which case anyone can add it (if they allow external bots).

  1. Once sideloading is configured as per the article mentioned above, you should see it work.

Connected and working in Microsoft Teams

I hope this gives enough insights into how easy it actually is to build a bot that can be run anywhere. The MS Bot Framework does indeed have lots of benefits and the SDK's are evolving.

6. Bot Analytics and Insights

Imagine you've developed a really nice bot now, and that you want may be using it internally in your organization, or you have even published it as an official bot somewhere. You want to see the insights and numbers on how it performs, right?

Let's check a few options out.

6.1. Application Insights

When setting up the project the way we did, we also get Application Insights hooked up to the resource in Azure so we can easiy track what's happening, how it's being used and if there's any unexpected errors happening.

  1. Head over to the dev portal for Bot Framework again: https://dev.botframework.com
  2. Click Settings for your bot
  3. Scroll down to the Analytics section and ensure the data is populated.

If there's no data configured here, follow the link Learn more to get started on that journey.

Ensure Application insights are configured

Now, to check out the real Application Insights data, follow these few steps:

  1. Head to your azure portal https://portal.azure.com
  2. Find the resource group for your new bot
  3. You'll see that there's an Application Insights resource connected to the bot. Click it:

Application Insights resource in Azure Portal

From here, you can access ALL insights from your bot. Well, the default ones at least.

If you want to add more App Insights into your code, you can do that as you would with any other Application Inisghts development task.

Since my bot is completely new off the shelf and there haven't been anyone else using it, I can't really see much insights yet - but there's some exceptions logged already:

Two exceptions in the Bot Framework bot

  • BotTimeoutException
  • Exception

These exceptions might be hard to find if you don't have any analytics. Imagine you're publishing an app used by hundreds of organizations, and something goes wrong - you'll need to quickly fix it and ensure that it doesn't happen again. App insights is a good first step to do this, with Bots as well as other resources. (Yes, I use App Insights with a lot of my real projects too).

We can drill down into these exceptions and see what really happened:

Application Insights showing Bot Framework 500 internal server error

Clicking where the arrow points will give you the full stack trace of what happened:

App Insights showing the Call Stack

Hopefully as the bot matures, you'll find that the inisghts can tell you usage patterns, unexpected errors and quickly find a remedy for anything which is breaking.

6.2. Simple analytics from the Bot Framework portal

From within the portal itself (well, you can access it through the dev portal for Bot Framework or through your Azure resource, but its the same place in the end), you can see some quick but valuable insights about your application and where and how it's being used.

Bot Framework analytics to quickly understand how the bot is being used

While not as comprehensive as the details you'll view directly in App Insights, it's enough to just see if your bot is being used and which channels are more popular.


With this post I hope that it's become a bit more clear just how easy it is to get started with building bots using the Microsoft Bot Framework!

I might go into further details with node.js bot development, in-depth C# bot development and building more complex bots using the SDK's available. But that's for another post - now we at least know how easy it is to get started.


AzureMicrosoft Teams.NET

Tobias Zimmergren Twitter

Hi, I'm Tobias! 👋 I write about Microsoft Azure, security, cybersecurity, compliance, cloud architecture, Microsoft 365, and general tech!

Reactions and mentions

Hi, I'm Tobias 👋

Tobias Zimmergren profile picture

Find out more about me.

Recent comments