หมายเหตุ
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลอง ลงชื่อเข้าใช้หรือเปลี่ยนไดเรกทอรีได้
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลองเปลี่ยนไดเรกทอรีได้
Invoke dialogs (referred as task modules in TeamsJS v1.x) from Microsoft Teams bots using TaskFetchAction buttons on Adaptive Cards. Dialogs provide a focused interaction by opening a pop-up window for the user, making them ideal for complex forms or multi-step workflows.
There are two ways of invoking dialogs:
- A new invoke message
task/fetch: Using theAction.Executecard action for Adaptive Cards withtask/fetch, either an HTML or Adaptive Card-based dialog is fetched dynamically from your bot. - Deep link URLs: Using the deep link syntax for dialogs, you can use the
Action.OpenUrlcard action for Adaptive Cards. With deep link URLs, the dialog URL or Adaptive Card body is already known to avoid a server round-trip relative totask/fetch.
Important
Each url and fallbackUrl must implement the HTTPS encryption protocol.
Note
In Teams client v1, dialogs were called task modules. They may occasionally be used synonymously.
Create a dialog launcher
To invoke a dialog from a bot, send an Adaptive Card with TaskFetchAction buttons. Each button includes data that your bot uses to determine which dialog content to return.
Warning
Microsoft's cloud services, including web versions of Teams, Outlook, and Microsoft 365 domains, are migrating to the *.cloud.microsoft domain. Perform the following steps as soon as possible to ensure your app continues to render on supported Microsoft 365 web client hosts:
Update TeamsJS library to v.2.19.0 or later. You must call
microsoftTeams.app.initialize()to avoid seeing a warning in the new domain. For more information about the latest release of TeamsJS, see Microsoft Teams JavaScript client library.If you've defined Content Security Policy (CSP) headers for your app, update the frame-ancestors directive to include the
*.cloud.microsoftdomain. To ensure backward compatibility during the migration, retain the existingframe-ancestorsvalues in your CSP headers. This approach ensures that your app continues to work across both existing and future Microsoft 365 host applications and minimizes the need for subsequent changes.
Update the following domain in the frame-ancestors directive of your app's CSP headers:
https://*.cloud.microsoft
The following steps provide instructions on how to invoke a dialog (referred as task module in TeamsJS v1.x) using task/fetch:
This image shows an Adaptive Card with a Buy
Action.Executecard action. The value of thetypeproperty istask/fetchand the rest of thedataobject can be of your choice.The bot receives a
card.actionactivity. In the Teams SDK, you handle this using theOnAdaptiveCardActionhandler. For more information, see Executing Actions.The bot creates an
ActionResponseobject and returns it. For more information on schema for responses, see the discussion on task/submit. The following code provides an example of the response body that contains a TaskInfo object embedded in a wrapper object:{ "task": { "type": "continue", "value": { "title": "Task module title", "height": 500, "width": "medium", "url": "https://contoso.com/msteams/taskmodules/newcustomer", "fallbackUrl": "https://contoso.com/msteams/taskmodules/newcustomer" } } }The
task/fetchevent and its response for bots is similar to themicrosoftTeams.tasks.startTask()function in the Microsoft Teams JavaScript client library (TeamsJS).Microsoft Teams displays the dialog.
The next section provides details on submitting the result of a dialog.
Submit the result of a dialog
When the user finishes with the dialog, the result is submitted back to your app. How submission works depends on the dialog content type:
- Adaptive Card (TaskInfo.card): When the user selects an
Action.Submitbutton, Teams sends a dialog submit event to your app. Your dialog submit handler receives the form data from the card. In C#, use the[TaskSubmit]attribute. In TypeScript, useapp.on('dialog.submit', ...). In Python, use@app.on_dialog_submit. - Webpage (TaskInfo.url): The webpage calls
microsoftTeams.tasks.submitTask(formData)from the TeamsJS client library, which triggers the same dialog submit event in your app.
Handle dialog submit events
When the user submits a dialog, the bot receives a task/submit invoke message. You have several options when responding:
| Response type | Scenario |
|---|---|
| No response | The simplest response is no response at all. Your bot isn't required to respond when the user finishes with the dialog. |
MessageTask |
Teams displays a message in a pop-up message box in the dialog. |
ContinueTask |
Allows you to chain sequences of Adaptive Cards together in a wizard or multi-step experience. |
The following tabs show how to handle dialog submit events in .NET, TypeScript, and Python:
using System.Text.Json;
using Microsoft.Teams.Api.TaskModules;
using Microsoft.Teams.Apps;
using Microsoft.Teams.Apps.Activities.Invokes;
using Microsoft.Teams.Apps.Annotations;
using Microsoft.Teams.Common.Logging;
[TaskSubmit]
public async Task<Microsoft.Teams.Api.TaskModules.Response> OnTaskSubmit([Context] Tasks.SubmitActivity activity, [Context] IContext.Client client, [Context] ILogger log)
{
var data = activity.Value?.Data as JsonElement?;
if (data == null)
{
log.Info("[TASK_SUBMIT] No data found in the activity value");
return new Microsoft.Teams.Api.TaskModules.Response(
new Microsoft.Teams.Api.TaskModules.MessageTask("No data found in the activity value"));
}
var submissionType = data.Value.TryGetProperty("submissiondialogtype", out var submissionTypeObj) && submissionTypeObj.ValueKind == JsonValueKind.String
? submissionTypeObj.ToString()
: null;
string? GetFormValue(string key)
{
if (data.Value.TryGetProperty(key, out var val))
{
if (val is JsonElement element)
return element.GetString();
return val.ToString();
}
return null;
}
switch (submissionType)
{
case "simple_form":
var name = GetFormValue("name") ?? "Unknown";
await client.Send($"Hi {name}, thanks for submitting the form!");
return new Microsoft.Teams.Api.TaskModules.Response(
new Microsoft.Teams.Api.TaskModules.MessageTask("Form was submitted"));
default:
return new Microsoft.Teams.Api.TaskModules.Response(
new Microsoft.Teams.Api.TaskModules.MessageTask("Unknown submission type"));
}
}
Multi-step dialog chaining
You can chain Adaptive Cards into a multi-step wizard by returning a ContinueTask response from the submit handler. Each step returns a new card, and the final step returns a MessageTask to close the dialog.
using System.Text.Json;
using Microsoft.Teams.Api;
using Microsoft.Teams.Api.TaskModules;
using Microsoft.Teams.Cards;
// Add these cases to your OnTaskSubmit method
case "webpage_dialog_step_1":
var nameStep1 = GetFormValue("name") ?? "Unknown";
var nextStepCardJson = $$"""
{
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "Email",
"size": "Large",
"weight": "Bolder"
},
{
"type": "Input.Text",
"id": "email",
"label": "Email",
"placeholder": "Enter your email",
"isRequired": true
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit",
"data": {"submissiondialogtype": "webpage_dialog_step_2", "name": "{{nameStep1}}"}
}
]
}
""";
var nextStepCard = JsonSerializer.Deserialize<AdaptiveCard>(nextStepCardJson)
?? throw new InvalidOperationException("Failed to deserialize next step card");
var nextStepTaskInfo = new TaskInfo
{
Title = $"Thanks {nameStep1} - Get Email",
Card = new Attachment
{
ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
Content = nextStepCard
}
};
return new Response(new ContinueTask(nextStepTaskInfo));
case "webpage_dialog_step_2":
var nameStep2 = GetFormValue("name") ?? "Unknown";
var emailStep2 = GetFormValue("email") ?? "No email";
await client.Send($"Hi {nameStep2}, thanks for submitting the form! We got that your email is {emailStep2}");
return new Response(new MessageTask("Multi-step form completed successfully"));
Bot Framework card actions vs. Adaptive Card Action.Submit actions
The schema for Bot Framework card actions is different from Adaptive Card Action.Submit actions and the way to invoke dialogs is also different. The data object in Action.Submit contains a msteams object so it doesn't interfere with other properties in the card. The following table shows an example of each card action:
| Bot Framework card action | Adaptive Card Action.Submit action |
|---|---|
{ |
{ |
Code sample
| Sample name | Description | .NET | Node.js | Manifest | Python |
|---|---|---|---|---|---|
| Dialog sample bots-V4 | This sample app demonstrate how to use Dialogs (referred as task modules in TeamsJS v1.x) using Bot Framework v4. | View | View | NA | View |
See also
Platform Docs