Botbuilder Compatibility
Migrating to SDK 2.1​
In SDK 2.1, the BotBuilder plugin is replaced by the Microsoft.Teams.Apps.BotBuilder NuGet package, which wires your existing ActivityHandler and CloudAdapter directly into ASP.NET Core without any additional plugin layer.
1. Replace packages
Remove the old SDK 2.0 plugin:
<!-- remove -->
<PackageReference Include="Microsoft.Teams.Plugins.AspNetCore.BotBuilder" Version="..." />
Add the SDK 2.1 compatibility package:
<!-- add -->
<PackageReference Include="Microsoft.Teams.Apps.BotBuilder" Version="..." />
2. Update Program.cs
Replace manual BotFramework registration with a single call:
// before (SDK 2.0 or raw BotBuilder)
builder.Services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
builder.Services.AddTransient<IBot, Bot>();
// after (SDK 2.1)
builder.AddTeamsBotFrameworkHttpAdapter();
builder.Services.AddTransient<IBot, Bot>();
Then map the messages endpoint:
app.MapPost("/api/messages", async (IBotFrameworkHttpAdapter adapter, IBot bot,
HttpRequest request, HttpResponse response, CancellationToken ct)
=> await adapter.ProcessAsync(request, response, bot, ct));
3. Keep your existing handlers
Your ActivityHandler (Bot.cs) and CloudAdapter implementations require no changes — they continue to work as-is.
Use Microsoft.Teams.Plugins.AspNetCore.BotBuilder and follow the plugin registration pattern shown below.
- Program.cs
- BotBuilderAdapter.cs
- ActivityHandler.cs
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Teams.Apps.BotBuilder;
public static partial class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder
.AddTeams()
.AddBotBuilder<Bot, BotBuilderAdapter, ConfigurationBotFrameworkAuthentication>();
var app = builder.Build();
var teams = app.UseTeams();
app.Run();
}
teams.OnMessage(async (context, cancellationToken) =>
{
await context.Client.Typing(cancellationToken);
await context.Client.Send($"hi from teams...", cancellationToken);
});
}
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Connector.Authentication;
// replace with your Adapter
public class BotBuilderAdapter : CloudAdapter
{
public BotBuilderAdapter(BotFrameworkAuthentication auth, ILogger<IBotFrameworkHttpAdapter> logger)
: base(auth, logger)
{
OnTurnError = async (turnContext, exception) =>
{
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
// Send a message to the user
await turnContext.SendActivityAsync("The bot encountered an error or bug.");
};
}
}
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
// replace with your ActivityHandler
public class Bot : ActivityHandler
{
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
var replyText = $"hi from botbuilder...";
await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);
}
}
The plugin connects your existing CloudAdapter and ActivityHandler to Teams SDK. When an activity arrives:
- The BotBuilder
ActivityHandlerprocesses it first (standard Bot Framework logic). - The Teams SDK handlers execute afterward.
This lets you incrementally migrate — both run on the same message:
hi from botbuilder...
hi from teams...