MSTeams消息扩展Bot中AdaptiveCard随机消失问题求助
问题分析与解决方案:Teams消息扩展AdaptiveCard非固定模式下消失
原因分析
- 临时会话上下文回收:非固定的消息扩展属于临时会话,Teams客户端会在请求完成后快速回收会话资源。如果卡片响应时序稍慢,客户端可能已清理会话上下文,导致卡片渲染后被自动移除;固定扩展使用持久会话,上下文不会被立即回收,因此卡片能稳定显示。
- 无效卡片触发自动清理:当前代码生成的AdaptiveCard仅包含
type和version字段,缺少body等核心内容,属于不完整卡片。非固定模式下Teams客户端对卡片有效性校验更严格,会自动丢弃无效卡片;固定模式下校验逻辑宽松,允许基础卡片显示。 - 实例化方式导致上下文丢失:每次处理请求时新建
ActionHandler实例,可能导致Bot Framework的上下文绑定不完整,非固定会话下这种不完整的上下文无法维持卡片的持久化状态。
解决方案
1. 修复AdaptiveCard的完整性
补充卡片必要结构,确保符合Teams的AdaptiveCard规范:
const card = CardFactory.adaptiveCard({ type: 'AdaptiveCard', version: '1.5', body: [ { type: 'TextBlock', text: '卡片内容示例', size: 'medium' } ] });
2. 复用ActionHandler实例(Nest.js依赖注入)
将ActionHandler注册为Nest.js的提供者,避免每次请求新建实例,确保上下文正确绑定:
// 在模块中注册ActionHandler @Module({ controllers: [BotController], providers: [ActionHandler] }) export class BotModule {} // 在BotController中注入ActionHandler @Controller() export class BotController { constructor(private readonly actionHandler: ActionHandler) {} @Post(['/api/messages']) public async messageExtensionCall( @I18n() i18n: I18nContext, @Req() req: Request, @Res() res: Response ): Promise<void> { const botFrameworkAuthentication = ...; const adapter = new CloudAdapter(botFrameworkAuthentication); await adapter.process(req, res, async (context) => { const actionId = context.activity.value.commandId; switch (actionId) { case 'Some_Action': await this.actionHandler.run(context); // 使用注入的实例 break; default: Logger.warn(`Unsupported action ${actionId}`); break; } }); } }
3. 配置会话状态持久化
为Bot添加会话状态存储,避免临时会话的上下文被快速回收:
import { MemoryStorage, ConversationState } from 'botbuilder'; // 在BotController中添加状态配置 @Controller() export class BotController { private readonly conversationState: ConversationState; constructor(private readonly actionHandler: ActionHandler) { const storage = new MemoryStorage(); // 生产环境建议使用Azure Blob等持久化存储 this.conversationState = new ConversationState(storage); } @Post(['/api/messages']) public async messageExtensionCall( @I18n() i18n: I18nContext, @Req() req: Request, @Res() res: Response ): Promise<void> { const botFrameworkAuthentication = ...; const adapter = new CloudAdapter(botFrameworkAuthentication); adapter.use(this.conversationState); // 注册会话状态 await adapter.process(req, res, async (context) => { // ... 原有逻辑 }); } }
4. 明确响应的返回格式
确保MessagingExtensionActionResponse结构完整,避免模糊的返回值:
public override async handleTeamsMessagingExtensionSubmitAction( context: TurnContext, action: MessagingExtensionAction ): Promise<MessagingExtensionActionResponse> { try { const card = CardFactory.adaptiveCard({ type: 'AdaptiveCard', version: '1.5', body: [{ type: 'TextBlock', text: '提交成功' }] }); return { composeExtension: { type: 'result', attachmentLayout: 'list', attachments: [card] } }; } catch (error) { Logger.error('Cannot create submit action response.', error); // 返回明确的错误响应,而非空对象 return { composeExtension: { type: 'message', text: '卡片生成失败,请重试' } }; } }
内容的提问来源于stack exchange,提问作者Relaxx
相关产品推荐
相关产品推荐

