By Nikhil | Azure Developer | Bot Framework Enthusiast
Introduction
So I was working on a project where I had to build a chatbot that could talk to users, understand what they are asking, and reply back intelligently. That is when I got introduced to Azure Bot Framework and Azure Bot Service.
Honestly, when I first started, I was confused — is Bot Framework and Bot Service the same thing? What is a Dialog? Why is there something called a Turn? It took me some time to connect all the dots.
In this blog I will try to explain everything from scratch — the way I wish someone had explained it to me when I started. I will keep it simple and practical so even if you are completely new to this, you can follow along.
Let's get started!
What is a Bot Anyway?
Before we jump into Azure stuff, let me explain what a bot actually is in simple terms.
A bot is just an application that can have a conversation with a user. Instead of a user clicking buttons and filling forms, they just type (or speak) naturally — and the bot understands and responds.
Some real world examples:
- Customer support chatbot on a bank website
- HR bot inside Microsoft Teams that answers employee queries
- E-commerce bot that helps you track your order
- Flight booking bot that asks you where you want to go
Bots are becoming very common in enterprise applications because they save time and reduce manual effort.
Azure Bot Framework vs Azure Bot Service — Are They Same?
This was my first confusion when I started. Let me clear it up.
Bot Framework is Microsoft's open source SDK (Software Development Kit) that you use to write the bot logic. Think of it as the toolkit you use to build your bot. It is available in C#, JavaScript and Python.
Azure Bot Service is the cloud platform on Azure that hosts and manages your bot. It connects your bot to different channels like Web Chat, Microsoft Teams, Slack etc.
Simple way to remember:
Bot Framework SDK = You build the bot here (code)
Azure Bot Service = You deploy and manage the bot here (cloud)
You build with Bot Framework and then deploy through Azure Bot Service. They work together but they are different things.
Architecture Overview
Before writing any code, it is good to understand how all the pieces fit together.
Here is what happens when a user sends a message:
- User types a message on Web Chat or Teams
- Message reaches Azure Bot Service
- Bot Service authenticates the request and converts it into a standard format
- Bot Service sends the message to your Bot API (your C# code)
- Your bot processes the message and generates a reply
- Reply goes back to Bot Service
- Bot Service delivers it to the user on their channel
The beauty of this is — your bot code stays the same regardless of which channel the user is on. Bot Service handles all the translation.
Prerequisites
Before we start, make sure you have these installed:
- Visual Studio 2022 with Azure development workload
- Azure Account (free tier works fine for practice)
- ngrok — for exposing your local bot to internet during development
- .NET 6 or higher
Step 1 — Create Your First Bot Project
Open Visual Studio 2022 and follow these steps:
- Click Create a new project
- Search for Bot Framework
- Select Core Bot template
- Give it a name like
MyFirstBot - Click Create
Visual Studio will generate a complete bot project for you with a proper folder structure.
Step 2 — Understanding the Project Structure
When you open the generated project, you will see something like this:
Let me explain the important files:
appsettings.json — This is where you put your Azure credentials like App ID, Password and Tenant ID.
Startup.cs — This is where all services are registered including State, Dialogs and the Bot adapter.
Controllers/BotController.cs — This is the entry point. All incoming messages hit the /api/messages endpoint here.
Bots/DialogBot.cs — This is the main bot class that receives activities and passes them to dialogs.
Dialogs/MainDialog.cs — This is where your conversation logic lives.
Step 3 — Key Concepts You Must Know
Let me explain the most important concepts before we go further.
What is an Activity?
Everything that happens in a conversation is called an Activity. When a user sends a message — that is an Activity. When a user joins the conversation — that is also an Activity. Even the typing indicator is an Activity.
The most common Activity type is message — which carries the actual text from the user.
// You can check the Activity type like this
if (turnContext.Activity.Type == ActivityTypes.Message)
{
// User sent a message
var userMessage = turnContext.Activity.Text;
}
What is a Turn?
A Turn is one complete round of conversation — the user sends one message and the bot sends one reply. That entire exchange is called a Turn.
User: "Hi" ← Start of Turn 1
Bot: "Hello!" ← End of Turn 1
User: "Book a flight" ← Start of Turn 2
Bot: "Where to?" ← End of Turn 2
What is TurnContext?
TurnContext is an object that is available during the entire Turn. It contains the incoming message, and methods to send a reply back.
// TurnContext gives you everything about the current turn
public async Task OnTurnAsync(ITurnContext turnContext,
CancellationToken cancellationToken)
{
// Read user message
var userMessage = turnContext.Activity.Text;
// Send reply
await turnContext.SendActivityAsync("Hello! How can I help?");
}
Step 4 — Understanding Dialogs
Dialogs are reusable components that manage a specific conversation flow. Think of a Dialog as a function that handles one specific task — like a registration flow, booking flow, or FAQ flow.
Types of Dialogs
WaterfallDialog — This is a step by step linear dialog. Each step asks something and moves to the next step.
// WaterfallDialog example — step by step flow
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
AskNameStepAsync, // Step 1: Ask name
AskAgeStepAsync, // Step 2: Ask age
ConfirmStepAsync, // Step 3: Confirm details
FinalStepAsync // Step 4: Save and finish
}));
ComponentDialog — This is a container that groups related dialogs together. Your MainDialog is a ComponentDialog.
PromptDialogs — These are specialized dialogs for collecting specific types of input from user:
-
TextPrompt— for any text input -
NumberPrompt— for numbers only -
ChoicePrompt— for multiple choice options -
ConfirmPrompt— for yes/no questions -
DateTimePrompt— for dates and times
Step 5 — State Management
This is a very important concept. By default, a bot has no memory — every Turn is independent. If you ask the user their name in Turn 1, the bot will forget it by Turn 2.
That is where State Management comes in.
Bot Framework provides three types of state:
UserState — Remembers data for a specific user across all conversations. Good for storing user profile, preferences etc.
ConversationState — Remembers data for the current conversation. Good for tracking which step of a dialog the user is on.
PrivateConversationState — Remembers data that is private to one user in one specific conversation.
// Register state in Startup.cs
services.AddSingleton<IStorage, MemoryStorage>(); // Use for local dev only
services.AddSingleton<UserState>();
services.AddSingleton<ConversationState>();
⚠️ Important: Use
MemoryStorageonly for local development and testing. It stores data in RAM and loses everything when the bot restarts. For production, always use Azure Blob Storage or Azure Cosmos DB.
Step 6 — Middleware Pipeline
Middleware in Bot Framework works exactly like ASP.NET Core middleware. Every Activity passes through the middleware pipeline before reaching your bot logic and after your bot sends a response.
Incoming Activity
↓
Logging Middleware
↓
State Middleware
↓
Your Bot Logic
↓
(Same pipeline in reverse for response)
Some built-in middleware:
-
AutoSaveStateMiddleware— automatically saves state after each turn -
ShowTypingMiddleware— shows typing indicator while bot is processing -
TranscriptLoggerMiddleware— logs all conversations
You can also write your own custom middleware for things like logging, translation, or profanity filtering.
Step 7 — Setup Azure Bot Service
Now that our bot code is ready, we need to connect it to Azure Bot Service.
Create App Registration
- Go to Azure Portal
- Navigate to Azure Active Directory → App Registrations
- Click New Registration
- Give it a name
- Select appropriate account type
- Click Register
After creating, note down:
-
Application (client) ID — this is your
MicrosoftAppId -
Directory (tenant) ID — this is your
MicrosoftAppTenantId
Then go to Certificates & Secrets and create a new Client Secret. Copy the Value immediately — you won't see it again!
⚠️ Common Mistake: People often copy the Secret ID instead of Secret Value. Always copy from the VALUE column, not the ID column.
Create Azure Bot Resource
- Azure Portal → Create a resource → Search Azure Bot
- Fill in bot handle and resource group
- Select appropriate App type
- Click Create
Update appsettings.json
{
"MicrosoftAppType": "SingleTenant",
"MicrosoftAppId": "your-app-id-here",
"MicrosoftAppPassword": "your-client-secret-value-here",
"MicrosoftAppTenantId": "your-tenant-id-here"
}
Step 8 — Local Testing with ngrok
During development your bot runs on localhost. But Azure Bot Service needs a public HTTPS URL to reach your bot. This is where ngrok comes in.
ngrok creates a public tunnel to your localhost.
# Start ngrok to expose port 3978
ngrok http 3978
Copy the HTTPS URL from ngrok and paste it in Azure Bot Service:
- Azure Portal → Your Bot → Configuration
- Set Messaging Endpoint to:
https://your-ngrok-url.ngrok-free.app/api/messages - Click Apply
⚠️ Important: Every time you restart ngrok the URL changes. You need to update it in Azure Bot Configuration every time.
Step 9 — Test Your Bot
Now run your project in Visual Studio (F5) and go to:
Azure Portal → Your Bot → Test in Web Chat
Type Hi and your bot should respond!
If you see a response — congratulations! Your first bot is working!
Common Errors and How I Fixed Them
I faced quite a few errors while setting this up. Here are the most common ones and how to fix them:
Operation returned an invalid status code 'Unauthorized'
- Check your
MicrosoftAppIdandMicrosoftAppPasswordin appsettings.json - Make sure you copied Secret VALUE not Secret ID
- Verify App type matches between Azure Bot and appsettings.json
Application was not found in the directory 'Bot Framework'
- This usually means App type mismatch — SingleTenant vs MultiTenant
- Verify your
MicrosoftAppTypein appsettings.json matches the Bot Service configuration
ngrok — Upgrade to WebSocket is required
- This is normal! It appears when you open the ngrok URL directly in browser
- The bot endpoint only accepts POST requests from Bot Framework
- Test through Azure Web Chat, not by opening the URL in browser
What is LUIS / CLU?
Most real bots need to understand what the user is saying in natural language. For example if user types "I want to book a ticket to Mumbai for next Friday" — your bot needs to understand:
- Intent — user wants to book a ticket (BookFlight)
- Entity — destination is Mumbai, date is next Friday
This is where LUIS (Language Understanding Intelligent Service) comes in. You train LUIS with example phrases and it learns to identify intents and entities from user messages.
⚠️ Note for interviews: LUIS is being retired and replaced by Azure AI Language — CLU (Conversational Language Understanding) in 2025. Mention this in interviews to show you are up to date.
Channels — Deploy Your Bot Everywhere
One of the best things about Azure Bot Service is Channels. You write your bot code once and connect it to multiple platforms.
Some popular channels:
- Web Chat — embed on any website
- Microsoft Teams — enterprise users
- Direct Line — for custom applications and mobile apps
- Slack — team collaboration
- Facebook Messenger — social platform
- WhatsApp — mobile users
For custom web or mobile apps, Direct Line is the recommended approach. You get a secret key and use the Direct Line SDK to connect your custom UI to the bot.
What I Learned from This Experience
Building my first bot was a great learning experience. A few things I want to highlight:
Start simple — Don't try to add LUIS, state management and everything at once. First get a simple echo bot working, then add features one by one.
Use Bot Framework Emulator — For local testing, the emulator is much easier than setting up ngrok and Azure. Connect directly to http://localhost:3978/api/messages with empty credentials.
Understand the flow — Once you understand the Turn, Activity, Dialog stack flow — everything else falls into place. It took me some time but once it clicked, it became easy.
State management is important — Don't underestimate this. A bot without proper state management will forget everything between turns and create a terrible user experience.
Next Steps
If you have got your first bot working, here is what you can explore next:
- Add LUIS / CLU — Make your bot understand natural language
- Adaptive Cards — Create rich UI cards with buttons, images and forms inside the chat
- Proactive Messaging — Make your bot send notifications without user initiating
- OAuth Authentication — Let users login through your bot
- Deploy to Azure App Service — Move from ngrok to proper production deployment
- Direct Line Integration — Embed your bot in a custom React or mobile app
Conclusion
Azure Bot Framework and Bot Service is a really powerful combination for building enterprise grade chatbots. Once you understand the core concepts — Activity, Turn, TurnContext, Dialogs, State — building bots becomes quite straightforward.
I hope this blog helped you get started. If you have any questions or faced any errors during setup, drop them in the comments — I will try to help based on my experience.
Happy coding!
If you found this helpful, do share it with your developer friends. Follow me for more Azure and .NET content.
Tags: #azure #botframework #dotnet #csharp #chatbot #azurebotservice #beginners













Top comments (0)