Bot Framework V4 C#:自适应卡片选中值无法传递至主对话下一步
解决Bot Framework V4 C#中自适应卡片Submit值无法传递到主对话的问题
看起来你遇到的核心问题是代码执行顺序错误,导致Dialog系统在你处理activity.Value之前就已经完成了当前轮次的处理,所以瀑布步骤HandleResponseAsync根本没拿到转换后的值。另外,代码末尾重复发送activity的操作也会干扰正常对话流程,我们一步步来修复:
1. 调整OnTurnAsync的执行顺序
Bot Framework里,base.OnTurnAsync是触发Dialog系统处理的关键。你之前先调用了base.OnTurnAsync,再去把activity.Value转成activity.Text——这时候Dialog已经处理完当前用户活动了,自然拿不到新的文本值。正确的顺序应该是先处理Value转Text,再交给Dialog处理:
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken)) { var activity = turnContext.Activity; // 先处理自适应卡片的Submit值,转成Text if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null) { activity.Text = JsonConvert.SerializeObject(activity.Value); } // 再调用base,让Dialog系统处理转换后的活动 await base.OnTurnAsync(turnContext, cancellationToken); await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken); await UserState.SaveChangesAsync(turnContext, false, cancellationToken); // 移除最后一行重复发送activity的代码,避免重复消息 switch (activity.Text) { case "{\"choice\":1}": break; case "{\"choice\":2}": var welcomeCard = CreateAdaptiveCardAttachment(); var response = CreateResponse(turnContext.Activity, welcomeCard); await turnContext.SendActivityAsync(response, cancellationToken); break; } }
2. 在HandleResponseAsync中解析值并传递给LUIS
现在瀑布步骤应该能捕获到序列化后的字符串了,我们把它反序列化成对象,提取选中的选项值,再传给LUIS:
首先定义一个匹配自适应卡片返回结构的类:
public class CardSelection { public int choice { get; set; } }
然后修改HandleResponseAsync:
private async Task<DialogTurnResult> HandleResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var userInput = stepContext.Result as string; if (!string.IsNullOrEmpty(userInput)) { // 反序列化拿到选中的选项 var selection = JsonConvert.DeserializeObject<CardSelection>(userInput); int selectedChoice = selection.choice; await stepContext.Context.SendActivityAsync($"你选中了选项: {selectedChoice}", cancellationToken: cancellationToken); // 把选中值传递给LUIS做意图识别 var luisResult = await _luisRecognizer.RecognizeAsync<YourLuisIntentClass>(stepContext.Context, cancellationToken); // 这里根据LUIS返回的意图做后续处理... } return await stepContext.NextAsync(); }
3. 更简洁的方案:直接读取Activity.Value
其实你完全不需要修改activity.Text,可以直接在瀑布步骤里读取stepContext.Context.Activity.Value,跳过序列化转Text的步骤:
private async Task<DialogTurnResult> HandleResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var activity = stepContext.Context.Activity; if (activity.Value != null) { var selection = JsonConvert.DeserializeObject<CardSelection>(activity.Value.ToString()); int selectedChoice = selection.choice; await stepContext.Context.SendActivityAsync($"你选中了选项: {selectedChoice}", cancellationToken: cancellationToken); // 传递给LUIS处理意图 var luisResult = await _luisRecognizer.RecognizeAsync<YourLuisIntentClass>(stepContext.Context, cancellationToken); // 处理意图逻辑... } return await stepContext.NextAsync(); }
这种情况下,你可以删掉OnTurnAsync里转换activity.Value到activity.Text的代码,流程会更清晰。
内容的提问来源于stack exchange,提问作者user64870
相关产品推荐
相关产品推荐

