如何在Task module提交触发时驱动Waterfall Dialog执行下一步
Teams 瀑布对话框接收Task Module提交并继续执行的实现方案
核心逻辑:task/submit属于Invoke类型活动,不会自动进入正在运行的瀑布对话框栈,需要手动将提交数据注入对话上下文,主动唤醒等待中的对话框流程。
前置依赖确认
- Bot类中已注入持久化的
ConversationState实例 - 已基于对话状态创建
DialogSet,所有业务对话框都注册在该DialogSet中 - 对话框栈状态会在每轮活动处理完成后正确保存
分步实现
1. 调整弹出Task Module的瀑布步逻辑
在瀑布流第二步(弹出Task Module的步骤),不要在弹出卡片后直接调用NextAsync()让流程往下走,而是返回EndOfTurn让对话框保持在当前步骤等待后续事件。同时在步骤入口加判断,检测到Task Module提交数据时直接流转到下一步。
private async Task<DialogTurnResult> Step2_ShowTaskModuleAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // 检测当前轮次是否携带Task Module提交数据 if (stepContext.Context.TurnState.TryGetValue("TaskModulePayload", out var submitPayload)) { // 携带提交数据,直接流转到下一个瀑布步 return await stepContext.NextAsync(submitPayload, cancellationToken); } // 无提交数据,为首次进入步骤,构造Task Module弹出卡片 var taskModuleInvoke = new TaskModuleAction("打开任务填写模块", new TaskModuleTaskInfo { Url = "你的任务模块前端页地址", Height = 550, Width = 650, Title = "信息填写" }); var card = new HeroCard { Buttons = new List<CardAction> { taskModuleInvoke } }.ToAttachment(); await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(card), cancellationToken); // 关键:返回EndOfTurn,暂停瀑布流,保持当前步骤等待 return Dialog.EndOfTurn; }
2. 改造OnTeamsTaskModuleSubmitAsync事件处理
在接收到Task Module提交事件时,将提交数据存入当前轮次的TurnState,主动创建对话框上下文唤醒等待中的瀑布流,最后保存对话状态。
// 注意:_conversationState、_dialogSet为Bot构造函数中注入并全局保存的实例 protected override async Task<TaskModuleResponse> OnTeamsTaskModuleSubmitAsync( ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken ) { // 将提交数据存入当前轮次状态,供瀑布步读取 turnContext.TurnState.Add("TaskModulePayload", taskModuleRequest.Data); // 创建对话框上下文,关联当前对话的对话框栈 var dialogContext = await _dialogSet.CreateContextAsync(turnContext, cancellationToken); // 触发对话框继续执行,唤醒等待中的瀑布步 await dialogContext.ContinueDialogAsync(cancellationToken); // 必须保存对话状态,否则栈状态变更不会生效 await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); // 可选:给用户发送提交成功提示 await turnContext.SendActivityAsync(MessageFactory.Text("提交已接收,正在处理..."), cancellationToken); return TaskModuleResponseFactory.CreateResponse("提交成功"); }
3. 后续瀑布步接收提交数据
瀑布流第三步就可以直接通过stepContext.Result拿到Task Module的提交内容,执行后续业务逻辑:
private async Task<DialogTurnResult> Step3_ProcessSubmitAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // 直接获取Task Module提交的结构化数据 var formData = stepContext.Result; // 这里写后续业务逻辑:数据校验、存库、返回结果卡片等 return await stepContext.NextAsync(cancellationToken); }
常见问题排查
- 瀑布流不继续:检查弹出Task Module的步骤是否错误返回了
NextAsync(),导致流程提前跑完、对话框栈被清空;检查SaveChangesAsync是否正确调用 - 拿不到提交数据:检查TurnState的Key是否一致,有没有在其他逻辑里覆盖了存入的载荷
- 生产环境偶发失效:检查
ConversationState是否用了持久化存储(如Cosmos DB、Blob Storage),内存存储仅适合本地调试,服务重启或多实例部署会丢状态
内容的提问来源于stack exchange,提问作者Snekithan
相关产品推荐
相关产品推荐

