如果你和我一樣,一直使用最新的 asp.net core 來開發teams bot的應用,那么你就會發現當你使用最新的 LTS 3.1版本或者 5.0 版本或者最新的 6.0 版本,asp.net core 默認使用System.Text.Json庫,所以當你在處理 Teams 發送來的請求的時候,如果還是使用類似于下面的代碼,那很多時候就是發現activity解析不出來,返回的response也不對。
[HttpPost("api/messages")]
public Activity GetMessage([FromBody]Activity activity)
{....return new Activity(){....};
}
為什么呢?從 Microsoft.Bot.Schema 的源代碼里的?Activity 定義?里可以發現原因:
using System.Collections.Generic;
using Newtonsoft.Json;namespace Microsoft.Bot.Schema
{public partial class Activity{[JsonProperty(PropertyName = "type")]public string Type { get; set; }[JsonProperty(PropertyName = "id")]public string Id { get; set; }[JsonProperty(PropertyName = "timestamp")]public System.DateTimeOffset? Timestamp { get; set; }[JsonProperty(PropertyName = "localTimestamp")]public System.DateTimeOffset? LocalTimestamp { get; set; }[JsonProperty(PropertyName = "localTimezone")]public string LocalTimezone { get; set; }[JsonProperty(PropertyName = "serviceUrl")]public string ServiceUrl { get; set; }[JsonProperty(PropertyName = "channelId")]public string ChannelId { get; set; }[JsonProperty(PropertyName = "from")]public ChannelAccount From { get; set; }...}
}
從上面的代碼可以看到,Activity 使用了 Newtonsoft.JSON 的 JsonProperty attribute 來說明如何 serialize 和 deserialize。既然是 Newtonsoft.JSON 的 attribute,那肯定對 System.Text.Json 不起作用了,就是說默認的 asp.net core 的 json 不會去讀取 JsonProperty attribute。除了 JsonProperty,Microsoft.Bot.Schema和其他bot的庫也使用了很多其他 Newtonsoft.JSON 的東西。
現在相信大家知道了原因,那如何解決?有這么幾種方法:
- 改變默認的 json,使用 Newtonsoft.JSON 先給項目安裝一個庫
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
然后在Startup文件中:
services.AddMvc().AddNewtonsoftJson();
或者
services.AddControllers().AddNewtonsoftJson(); services.AddControllersWithViews().AddNewtonsoftJson(); services.AddRazorPages().AddNewtonsoftJson();
- 手動的使用 Newtonsoft.JSON 來做序列化和反序列化
[HttpPost]
[Route("api/extension")]
public async Task<IActionResult> Post()
{using var reader = new StreamReader(Request.Body);var activity = JsonConvert.DeserializeObject<Activity>(await reader.ReadToEndAsync());...var responseJson = JsonConvert.SerializeObject(responseActivity);return Content(responseJson, "application/json");
}
- 自己定義一些需要用到的結構 (只適用于簡單的應用,比如:outgoing webhook)
public record Activity
{[JsonPropertyName("text")]public string Text { get; init; }
}
上面的 JsonPropertyName 是 System.Text.Json 里的一種 attribute。
不過,最終的解決方案,肯定是微軟官方的這些 Bot,Teams 的library可以支持最新的 System.Text.Json,希望這天可以快點到來。