You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bot Framework中如何向Hero Card传递不显示的任务ID并取回

解决Bot Framework Hero Card隐藏传递任务ID的问题

嘿,我来帮你搞定这个需求!要实现“卡片不显示任务ID,但选中时后端能获取并存储”的效果,核心思路是把任务ID藏在卡片按钮的交互参数里,用户看不到,但后端能拿到。下面是具体的实现步骤和代码示例:

一、创建带隐藏任务ID的Hero Card

Hero Card的按钮支持PostBack类型——这种类型的按钮点击后,会把你设置的value参数悄悄发给后端,而用户在聊天界面只会看到按钮的标题,完全看不到任务ID。

假设你有一个任务列表,每个任务包含TaskId和TaskName,可以这样生成卡片:

// 示例任务列表
var tasks = new List<TaskItem>
{
    new TaskItem { TaskId = "task_001", TaskName = "完成项目需求文档" },
    new TaskItem { TaskId = "task_002", TaskName = "修复用户登录BUG" },
    new TaskItem { TaskId = "task_003", TaskName = "部署测试环境" }
};

// 批量生成Hero Card
var heroCards = tasks.Select(task => new HeroCard
{
    Title = task.TaskName,
    // 可以添加副标题、图片等其他展示内容
    Subtitle = "点击下方按钮选择此任务",
    Buttons = new List<CardAction>
    {
        // 用PostBack类型按钮,把任务ID放到value里
        new CardAction(ActionTypes.PostBack, title: "选择任务", value: task.TaskId)
    }
}).ToList();

// 组装成轮播消息发送给用户
var carouselReply = MessageFactory.Carousel(heroCards);
await turnContext.SendActivityAsync(carouselReply, cancellationToken);

二、后端捕获并存储任务ID

当用户点击卡片按钮后,Bot会收到一条PostBack类型的消息,你需要在消息处理逻辑中提取value字段的任务ID,然后存储到内存(比如对话状态、全局缓存等)。

1. 临时存储(当前对话回合有效)

如果只需要在当前回合使用这个ID,可以用TurnState:

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    // 检查是否是PostBack消息
    if (turnContext.Activity.Value != null)
    {
        // 提取任务ID
        var selectedTaskId = turnContext.Activity.Value.ToString();
        
        // 存储到TurnState,仅当前回合有效
        turnContext.TurnState["SelectedTaskId"] = selectedTaskId;
        
        // 给用户反馈(不用显示ID)
        await turnContext.SendActivityAsync("已选中任务,后续将执行相关操作", cancellationToken: cancellationToken);
        
        // 这里可以直接调用API
        // await CallTaskApi(selectedTaskId);
    }
    else
    {
        await turnContext.SendActivityAsync("请通过卡片选择任务", cancellationToken: cancellationToken);
    }
}

2. 持久存储(跨对话回合有效)

如果需要在后续对话中继续使用这个ID,建议用ConversationState(对话状态):

首先定义一个对话状态类:

public class ConversationData
{
    public string SelectedTaskId { get; set; }
}

然后在Bot的构造函数中注入ConversationState,并在消息处理中保存:

private readonly ConversationState _conversationState;
private readonly IStatePropertyAccessor<ConversationData> _conversationDataAccessor;

public YourBot(ConversationState conversationState)
{
    _conversationState = conversationState;
    _conversationDataAccessor = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
}

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    if (turnContext.Activity.Value != null)
    {
        var selectedTaskId = turnContext.Activity.Value.ToString();
        
        // 获取对话状态实例
        var conversationData = await _conversationDataAccessor.GetAsync(turnContext, () => new ConversationData());
        // 保存任务ID
        conversationData.SelectedTaskId = selectedTaskId;
        // 持久化到状态存储
        await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        
        await turnContext.SendActivityAsync("任务已选中,后续操作将基于此任务执行", cancellationToken: cancellationToken);
    }
}

三、后续使用任务ID

之后需要调用API时,直接从存储中取出ID即可:

// 从ConversationState中取出
var conversationData = await _conversationDataAccessor.GetAsync(turnContext, () => new ConversationData());
var taskId = conversationData.SelectedTaskId;

// 调用API
var apiResponse = await HttpClient.GetAsync($"https://your-api-url/tasks/{taskId}");

这样就完美实现了你的需求:卡片上看不到任务ID,用户选中后后端能安全获取并存储,后续随时调用~

内容的提问来源于stack exchange,提问作者user9463688

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:07:42