When posting to an ASP.NET Core 3.1 web app, “[FromBody]MyClass data” is often null
我最近在从 .NET Core 2.2 升级到 3.1 后遇到了这个有趣(令人沮丧)的问题。 以前我会将数据发布到网络应用程序,接收方法看起来像这样:
public IActionResult OnPostAddNewDataAsync([FromBody]MyClass data)
{
//...
}
其中 MyClass
可能是这样的:
public class MyClass
{
public string Field1 {get; set;}
public integer Value1 {get; set;}
}
(作为参考,要从 Javascript
访问端点,您可以这样做:
await PostDataAsync("AddNewData", {
"Field1": "Hello I am",
"Value1": 7
});
async function PostDataAsync(handler, data)
{
return await $.ajax({
url: window.location.pathname + "?handler=" + handler,
type: "POST",
contentType: "application/json",
headers:
{
RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
},
data: JSON.stringify(data)
});
}
更新 .NET Core 3.1 后,我的许多 POST
方法都停止工作,并且 [FromBody]
值为 null
。
注意:作为升级到 .NET Core 3.1 的一部分,我删除了对 Newtonsoft.Json
的引用,决定尝试使用新的 System.Text.Json
。 事实证明这很重要!
答案
如前所述,删除了对 Newtonsoft.Json
的引用,将任何自动 Json
转换留给 System.Text.Json
处理。 事实证明,这是问题的原因,因为 System.Text.Json
不那么灵活(Microsoft 自己是这样说的,并且打算如此:How to migrate from Newtonsoft.Json to System.Text.Json) .
在 .NET Core 3 之前,ASP.NET Core 内部使用 Newtonsoft.Json
,现在改用 System.Text.Json
。
一个例子是数字字段,例如 MyClass.Value1
。 如果您从 Javascript 传递"10"
或 10
,Newtonsoft.Json
将处理它并将两者都识别为 10
。默认情况下使用 System.Text.Json
,该字段不能包含引号,如果您在 Json
中发布它,您将得到一个空 [FromBody]
值。
解决此问题的最快方法是在这些情况下恢复为 Newtonsoft.Json
,这很容易通过以下方式完成:
- 安装 Nuget 包
Microsoft.AspNetCore.Mvc.NewtonsoftJson
- 在
Startup.cs
中,更新以下方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages().AddNewtonsoftJson();
//All your other code:
//...
}
这是直接从这里获取的。
进行此更改后,一切再次按预期工作。
我知道可以使用自定义解析器配置 System.Text.Json
来处理这些情况(我在其他地方确实使用过),但我有几十种 POST
方法,而不是更新所有方法以使用新方法, 如上所述,这样做要容易得多。