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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:43:17