将对话与机器人配合使用

使用 TaskFetchAction 自适应卡片上的按钮从Microsoft Teams 机器人调用 (TeamsJS v1.x) 中称为任务模块的对话。 对话框通过为用户打开弹出窗口来提供重点交互,使其成为复杂窗体或多步骤工作流的理想选择。

有两种调用对话的方法:

  • 新的调用消息task/fetch:将 Action.Execute 卡 操作用于自适应卡片和 task/fetch,将从机器人动态提取基于 HTML 或自适应卡片的对话。
  • 深层链接 URL:使用对话的深层链接语法,可以对自适应卡片使用 Action.OpenUrl 卡 操作。 使用深层链接 URL 时,对话 URL 或自适应卡片正文已已知,以避免相对于 task/fetch的服务器往返。

重要

每个 urlfallbackUrl 都必须实现 HTTPS 加密协议。

注意

在 Teams 客户端 v1 中,对话称为任务模块。 它们可能偶尔使用同义词。

创建对话框启动器

若要从机器人调用对话,请发送带有 TaskFetchAction 按钮的自适应卡片。 每个按钮都包含机器人用于确定要返回的对话内容的数据。

警告

Microsoft的云服务(包括 Web 版本的 Teams、Outlook 和 Microsoft 365 域)正在迁移到域 *.cloud.microsoft 。 请尽快执行以下步骤,确保应用继续在受支持的 Microsoft 365 Web 客户端主机上呈现:

  1. 将 TeamsJS 库更新到 v.2.19.0 或更高版本。 必须调用 microsoftTeams.app.initialize() 以避免在新域中看到警告。 有关最新版本的 TeamsJS 的详细信息,请参阅 Microsoft Teams JavaScript 客户端库

  2. 如果已为应用定义了 内容安全策略 (CSP) 标头,请更新 frame-ancestors 指令以包含域 *.cloud.microsoft 。 为确保迁移过程中的向后兼容性,请保留 CSP 标头中的现有 frame-ancestors 值。 此方法可确保应用继续跨现有和将来Microsoft 365 主机应用程序工作,并最大程度地减少后续更改的需求。

在应用的 CSP 标头的 指令中 frame-ancestors 更新以下域:

https://*.cloud.microsoft

任务/提取请求或答复

以下步骤说明如何使用 调用 TeamsJS v1.x) task/fetch中称为任务模块的对话 (:

  1. 此图显示了具有“购买Action.Execute卡”操作的自适应卡片。 type 属性的值是 task/fetchdata 对象的其余部分可自行选择。

  2. 机器人接收活动 card.action 。 在 Teams SDK 中,可以使用 处理程序处理此问题 OnAdaptiveCardAction 。 有关详细信息,请参阅 执行操作

  3. 机器人创建并 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) 中的函数。

  4. 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 操作
{
“type”: “invoke”,
“title”: “Buy”,
“value”: {
“type”: “task/fetch”,
<...>
}
}
{
“type”: “Action.Submit”,
“id”: “btnBuy”,
“title”: “Buy”,
“data”: {
<...>,
“msteams”: {
“type”:“task/fetch”
}
}
}

代码示例

示例名称 Description .NET Node.js 清单 Python
对话示例 bots-V4 此示例应用演示如何使用 Bot Framework v4 在 TeamsJS v1.x) 中使用对话框 (称为任务模块。 View View 不适用 View

另请参阅