Create a message extension
In this unit, you learn how to create a message extension. You also learn how to run and debug your message extension in Microsoft Teams using Teams Toolkit.
To create a message extension, you need the following components:
- Azure Bot resource to register your web service as a bot with the Bot Framework
- Web service to handle user interactions with the message extension
- App manifest to define the message extension capabilities in Microsoft Teams
Configure Azure Bot resource
The Azure Bot resource is used to register your web service as a bot with the Bot Framework. A Microsoft Entra app registration is required to create an Azure Bot resource. The app registration provides a secure way to authenticate and authorize your bot. The web service uses the Microsoft Entra app registration credentials to authenticate with the bot service.
The following code snippet shows how to create an Azure Bot resource using Bicep:
resource botService 'Microsoft.BotService/botServices@2021-03-01' = {
kind: 'azurebot'
location: 'global'
name: 'botService'
properties: {
displayName: 'Bot Service'
endpoint: 'https://webservice.contoso.com/api/messages'
msaAppId: '00000000-0000-0000-0000-000000000000'
}
sku: {
name: botServiceSku
}
}
The endpoint property specifies the messaging endpoint exposed on the web service that the bot service uses to send requests when a user interacts with the message extension. The msaAppId property specifies the Microsoft Entra app registration ID used to authenticate the bot service with the web service.
Channels are used to connect the bot service with messaging platforms such as Microsoft Teams, Slack, Facebook Messenger, and more.
The following code snippet shows how to configure the Microsoft Teams and Microsoft 365 (Outlook and Microsoft 365 Copilot) channels on the Azure Bot resource:
resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
parent: botService
location: 'global'
name: 'MsTeamsChannel'
properties: {
channelName: 'MsTeamsChannel'
}
}
resource botServiceM365ExtensionsChannel 'Microsoft.BotService/botServices/channels@2022-06-15-preview' = {
parent: botService
location: 'global'
name: 'M365Extensions'
properties: {
channelName: 'M365Extensions'
}
}
Configure web service
The web service is a web app that contains the message extension code. The web service is responsible for handling user interactions with the message extension and uses the Bot Framework SDK to communicate with the bot service.
To handle user interactions, you implement:
- A messaging endpoint
- A Bot Adapter
- A Bot Activity Handler
The messaging endpoint is used to receive requests from the bot service. The messaging endpoint is exposed on the web service and passes the requests to the Bot Adapter for processing.
The following code snippet shows how to configure the messaging endpoint:
[Route("api/messages")]
[ApiController]
public class BotController : ControllerBase
{
private readonly IBotFrameworkHttpAdapter Adapter;
private readonly IBot Bot;
public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
{
Adapter = adapter;
Bot = bot;
}
[HttpPost, HttpGet]
public async Task PostAsync()
{
await Adapter.ProcessAsync(Request, Response, Bot);
}
}
The Bot Adapter is used to connect the bot service with the web service. The Bot Adapter is responsible for processing incoming requests from the bot service and invoking the bot activity handler. The web service authenticates with the bot service using the Microsoft Entra app registration credentials used to register the Azure Bot resource with the Bot Framework.
The following code snippet shows how to configure the Bot Adapter in the web service:
// Create the Bot Framework Authentication to be used with the Bot Adapter.
var config = builder.Configuration.Get<ConfigOptions>();
builder.Configuration["MicrosoftAppType"] = "MultiTenant";
builder.Configuration["MicrosoftAppId"] = config.BOT_ID;
builder.Configuration["MicrosoftAppPassword"] = config.BOT_PASSWORD;
builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();
// Create the Bot Framework Adapter with error handling enabled.
builder.Services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
builder.Services.AddTransient<IBot, SearchApp>();
To process the user search query and return search results, implement a Bot Activity Handler that inherits from the TeamsActivityHandler class provided by the Bot Framework SDK and override the OnTeamsMessagingExtensionQueryAsync method.
The following code snippet shows how to configure the Bot Activity Handler in the web service:
public class SearchApp : TeamsActivityHandler
{
protected override async Task<MessagingExtensionResponse> OnTeamsMessagingExtensionQueryAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken)
{
var text = query?.Parameters?[0]?.Value as string ?? string.Empty;
var card = await File.ReadAllTextAsync(Path.Combine(".", "Resources", "card.json"), cancellationToken);
var template = new AdaptiveCards.Templating.AdaptiveCardTemplate(card);
return new MessagingExtensionResponse
{
ComposeExtension = new MessagingExtensionResult
{
Type = "result",
AttachmentLayout = "list",
Attachments = [
new MessagingExtensionAttachment
{
ContentType = AdaptiveCard.ContentType,
Content = JsonConvert.DeserializeObject(template.Expand(new { text })),
Preview = new ThumbnailCard { Title = text }.ToAttachment()
}
]
}
};
}
}
Configure search command
The app manifest is a JSON file that defines the app's metadata and configuration. It defines the functionalities the app provides, such as message extensions. The app manifest is included within the app package. The app package is a ZIP file that you upload to Microsoft Teams to install the app.
The following code snippet shows how a search command is defined in the app manifest:
"composeExtensions": [
{
"botId": "4cc3ac43-d581-403d-8bbf-ff9c0fbf3fb2",
"commands": [
{
"id": "Search",
"type": "query",
"title": "Products",
"description": "Find products by name",
"initialRun": true,
"fetchTask": false,
"context": [
"commandBox",
"compose",
"message"
],
"parameters": [
{
"name": "ProductName",
"title": "Product name",
"description": "The name of the product as a keyword",
"inputType": "text"
}
]
}
]
}
]
A command can contain one or more parameters. A parameter is a field that is displayed in the user interface. In this example, the command has a single parameter named ProductName. The parameter is a text field that the user fills in with the name of the product they're searching for.
Teams Toolkit for Visual Studio
Teams Toolkit for Visual Studio is an extension that provides tools to create, debug, and deploy Microsoft Teams apps. Teams Toolkit integrates with Visual Studio to streamline the development process and provide a seamless experience for building Microsoft Teams apps.
Teams Toolkit scaffolds a solution containing two projects, a web service project and a Teams app project. The web service project contains the message extension code and the app project contains the app manifest and other resources required to run the app in Microsoft Teams.
Teams Toolkit integrates with the Dev tunnels feature in Visual Studio to enable communication between the bot service and the locally running web service. Dev tunnels expose the web service beyond your machine to allow the bot service to reach it.