使用 TaskFetchAction 自适应卡片上的按钮从Microsoft Teams 机器人调用 (TeamsJS v1.x) 中称为任务模块的对话。 对话框通过为用户打开弹出窗口来提供重点交互,使其成为复杂窗体或多步骤工作流的理想选择。
有两种调用对话的方法:
- 新的调用消息
task/fetch:将Action.Execute卡 操作用于自适应卡片和task/fetch,将从机器人动态提取基于 HTML 或自适应卡片的对话。 - 深层链接 URL:使用对话的深层链接语法,可以对自适应卡片使用
Action.OpenUrl卡 操作。 使用深层链接 URL 时,对话 URL 或自适应卡片正文已已知,以避免相对于task/fetch的服务器往返。
重要
每个 url 和 fallbackUrl 都必须实现 HTTPS 加密协议。
注意
在 Teams 客户端 v1 中,对话称为任务模块。 它们可能偶尔使用同义词。
创建对话框启动器
若要从机器人调用对话,请发送带有 TaskFetchAction 按钮的自适应卡片。 每个按钮都包含机器人用于确定要返回的对话内容的数据。
警告
Microsoft的云服务(包括 Web 版本的 Teams、Outlook 和 Microsoft 365 域)正在迁移到域 *.cloud.microsoft 。 请尽快执行以下步骤,确保应用继续在受支持的 Microsoft 365 Web 客户端主机上呈现:
将 TeamsJS 库更新到 v.2.19.0 或更高版本。 必须调用
microsoftTeams.app.initialize()以避免在新域中看到警告。 有关最新版本的 TeamsJS 的详细信息,请参阅 Microsoft Teams JavaScript 客户端库。如果已为应用定义了 内容安全策略 (CSP) 标头,请更新 frame-ancestors 指令以包含域
*.cloud.microsoft。 为确保迁移过程中的向后兼容性,请保留 CSP 标头中的现有frame-ancestors值。 此方法可确保应用继续跨现有和将来Microsoft 365 主机应用程序工作,并最大程度地减少后续更改的需求。
在应用的 CSP 标头的 指令中 frame-ancestors 更新以下域:
https://*.cloud.microsoft
以下步骤说明如何使用 调用 TeamsJS v1.x) task/fetch中称为任务模块的对话 (:
此图显示了具有“购买
Action.Execute卡”操作的自适应卡片。type属性的值是task/fetch,data对象的其余部分可自行选择。机器人接收活动
card.action。 在 Teams SDK 中,可以使用 处理程序处理此问题OnAdaptiveCardAction。 有关详细信息,请参阅 执行操作。机器人创建并
ActionResponse返回对象。 有关响应架构的详细信息,请参阅 有关任务/提交的讨论。 以下代码提供了一个响应正文示例,其中包含嵌入包装器 对象中的 TaskInfo 对象:{ "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" } } }机器人
task/fetch的事件及其响应类似于microsoftTeams.tasks.startTask()Microsoft Teams JavaScript 客户端库中 (TeamsJS) 中的函数。Microsoft Teams 显示对话框。
下一部分提供有关提交对话结果的详细信息。
提交对话框的结果
当用户完成对话框时,结果将提交回你的应用。 提交的工作原理取决于对话框内容类型:
-
自适应卡片 (TaskInfo。卡) :当用户选择按钮
Action.Submit时,Teams 会将对话框提交事件发送到你的应用。 对话框提交处理程序从卡接收表单数据。 在 C# 中,使用[TaskSubmit]特性。 在 TypeScript 中,使用app.on('dialog.submit', ...)。 在 Python 中,使用@app.on_dialog_submit。 -
网页 (TaskInfo.url) :来自 TeamsJS 客户端库的网页调用
microsoftTeams.tasks.submitTask(formData),这会在应用中触发相同的对话提交事件。
处理对话框提交事件
当用户提交对话时,机器人会收到调用 task/submit 消息。 响应时有几个选项:
| 响应类型 | 应用场景 |
|---|---|
| 无响应 | 最简单的答复根本不是答复。 当用户完成对话时,机器人不需要做出响应。 |
MessageTask |
Teams 在对话框的弹出消息框中显示一条消息。 |
ContinueTask |
允许在向导或多步骤体验中将自适应卡片序列链接到一起。 |
以下选项卡演示如何在 .NET、TypeScript 和 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"));
}
}
多步骤对话链接
可以通过从提交处理程序返回 ContinueTask 响应,将自适应卡片链接到多步骤向导。 每个步骤返回一个新的卡,最后一个步骤返回 以MessageTask关闭对话框。
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 卡片操作与自适应卡片操作。提交操作
Bot Framework 卡 操作的架构不同于自适应卡片Action.Submit操作,调用对话的方式也不同。 中的 dataAction.Submit 对象包含一个 msteams 对象,因此它不会干扰卡中的其他属性。 下表显示了每个卡片操作的示例:
| Bot Framework 卡片操作 | 自适应卡片 Action.Submit 操作 |
|---|---|
{ |
{ |
代码示例
| 示例名称 | Description | .NET | Node.js | 清单 | Python |
|---|---|---|---|---|---|
| 对话示例 bots-V4 | 此示例应用演示如何使用 Bot Framework v4 在 TeamsJS v1.x) 中使用对话框 (称为任务模块。 | View | View | 不适用 | View |