处理AdaptiveCard Action时触发‘Sorry, my bot code is having an issue’报错
看起来你遇到的是AdaptiveCard Action.Submit触发异常的问题,而且这个情况只出现在新项目里——确实挺头疼的,毕竟同代码在其他项目正常。结合你描述的现象(卡片显示正常、文字输入能触发Dialog、点击按钮调试时MessageController命中但崩溃),我整理了几个大概率的排查方向和解决方法:
1. 先捕获具体异常信息,别再靠泛泛的报错
你的MessageController里没有异常处理逻辑,一旦Conversation.SendAsync内部抛出异常,就会直接返回500错误,导致Bot显示那句通用报错。先给控制器加个try-catch,拿到具体的错误栈,这是定位问题的关键:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity) { try { if (activity.Type == ActivityTypes.Message) { ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); await Conversation.SendAsync(activity, () => new RootDialog()); } return Request.CreateResponse(HttpStatusCode.OK); } catch (Exception ex) { // 调试时可以直接返回错误信息,上线后改成日志记录 return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex); } }
加上这个后,点击按钮时就能看到具体的异常原因(比如反序列化失败、空引用等),而不是模糊的“bot code is having an issue”。
2. 检查Newtonsoft.Json版本兼容性
Bot Builder(尤其是v3版本)对Newtonsoft.Json的版本有严格依赖,很多时候跨项目的兼容性问题都源于这个包的版本不一致。你说回滚了bot.builder和bot.connector,但可能漏了Newtonsoft.Json:
- 打开正常项目的NuGet包管理器,查看Newtonsoft.Json的具体版本(比如v9.0.1或v10.0.3是旧版Bot常用的)
- 在新项目里强制安装完全相同的版本,避免版本冲突导致Action.Submit的payload反序列化崩溃
3. 确认Dialog的MessageReceivedAsync是否处理了Activity.Value
AdaptiveCard的Action.Submit发送的Activity类型还是Message,但它的核心数据在activity.Value字段里,而activity.Text是空的。如果你的MessageReceivedAsync只处理了文本输入,没判断Value,很可能会抛出空引用异常:
调整你的MessageReceivedAsync逻辑,加入对Value的处理:
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) { var activity = await result as Activity; string actionTrigger = null; // 先处理AdaptiveCard的Submit动作 if (activity.Value != null) { // 反序列化卡片提交的数据 var submitData = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(activity.Value.ToString()); actionTrigger = submitData.action?.ToString(); // 拿到你定义的"requestContact" } else { // 处理普通文本输入 actionTrigger = activity.Text; } // 后续根据actionTrigger执行对应逻辑 if (actionTrigger == "requestContact") { // 处理创建在线请求的逻辑 await context.PostAsync("Processing your contact request..."); } else { await context.PostAsync($"You said: {actionTrigger}"); } context.Wait(MessageReceivedAsync); }
如果之前的代码里直接用activity.Text而没判断是否为空,点击按钮时就会因为activity.Text是空值触发异常。
4. 验证Action.Submit的Payload是否正确传递
调试时在MessageController里打印Activity的完整Json,确认Value字段是否包含你定义的action: "requestContact":
// 在try块里加这句,查看提交的Activity内容 var activityJson = Newtonsoft.Json.JsonConvert.SerializeObject(activity); System.Diagnostics.Debug.WriteLine(activityJson);
如果Value字段是空的或者被篡改,那可能是卡片生成时的问题(不过你说卡片显示正常,这个概率较低,但可以排除)。
内容的提问来源于stack exchange,提问作者Kevin D.

