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

Bot Framework技术问询:在消息线程中插入消息后如何终止对话

解决Teams Bot自适应卡片提交后触发初始选择提示的问题

你的问题核心在于:当Bot处于等待用户选择初始选项的对话状态时,自适应卡片提交的消息会被路由到当前等待的对话步骤,而卡片提交的内容不是有效的选择项,导致Prompt重新触发初始选择提示。下面提供几种可行的解决方案,都可以兼容你使用RootDialog类方法的需求:

方案一:在RootDialog中提前捕获卡片提交的消息

通过重写RootDialog的MessageReceivedAsync方法,优先处理自适应卡片提交的消息,避免其进入选择提示的重试逻辑:

public override async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
    var incomingActivity = await result;
    
    // 检查是否是自适应卡片提交的消息(通过Value属性判断)
    if (incomingActivity.Value != null)
    {
        // 反序列化提交的数据到你定义的模型类
        var submittedData = JsonConvert.DeserializeObject<YourCardDataModel>(incomingActivity.Value.ToString());
        
        // 调用RootDialog内的方法处理提交的数据,这里可以使用context对象操作状态或发送回复
        await HandleCardSubmission(context, submittedData);
        
        // 结束当前等待的对话步骤,避免继续触发选择提示
        context.Done<object>(null);
        return;
    }
    
    // 如果不是卡片提交,交给默认的对话流程处理(比如初始选择提示)
    await base.MessageReceivedAsync(context, result);
}

// 你可以在RootDialog中新增这个方法来处理卡片提交
private async Task HandleCardSubmission(IDialogContext context, YourCardDataModel data)
{
    // 这里可以使用context收集/存储数据,比如保存到用户状态
    context.UserData.SetValue("SubmittedNote", data.newnote);
    
    // 向用户发送确认消息
    await context.PostAsync($"Thanks for your submission! We received: {data.newnote}");
    
    // 如果需要,可重新启动初始选择流程,或者进入其他对话步骤
    // context.Wait(ShowInitOptions);
}

方案二:在MessageController中终止当前对话栈再处理提交

如果需要在API层面先拦截卡片提交,可以修改ApiController的PostAsync方法,先结束当前对话栈,再处理数据:

public async Task<HttpResponseMessage> PostAsync([FromBody]Activity activity)
{
    if (activity.Type == ActivityTypes.Message)
    {
        // 判断是否为自适应卡片提交
        if (activity.Value != null)
        {
            var dialogState = activity.GetState<DialogState>();
            var dialogContext = new DialogContext(ConversationContainer, activity, dialogState);
            
            // 终止当前对话栈,清除等待状态
            await dialogContext.EndDialogAsync();
            
            // 处理提交的数据,这里可以实例化RootDialog调用其方法
            var rootDialog = new RootDialog();
            var submittedData = JsonConvert.DeserializeObject<YourCardDataModel>(activity.Value.ToString());
            await rootDialog.HandleCardSubmission(dialogContext.Context, submittedData);
            
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        
        // 处理普通对话消息
        await Conversation.SendAsync(activity, () => new RootDialog());
    }
    else
    {
        HandleSystemMessage(activity);
    }
    return Request.CreateResponse(HttpStatusCode.OK);
}

关键原理说明

当你调用PromptDialog.Choice后,Bot的对话栈会将当前步骤标记为"等待用户选择",所有后续消息都会被路由到这个步骤。如果消息不符合选择要求,Prompt会自动重试显示选择提示。通过提前捕获卡片提交的消息并结束当前等待步骤,就能避免这个问题,同时你依然可以使用context对象来收集和处理数据,和ShowInitOptions中的上下文保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:42:35