为什么 ASP.NET Web API 2 和 ASP.NET Core 3.1 Web API 之间的行为不同?

Why different behavior between ASP.NET Web API 2 & ASP.NET Core 3.1 Web API?

我将以下数据发布到 2 个不同的 api 端点,一个在 ASP.NET Web API 2 应用程序中,另一个在 ASP.NET 中核心 3.1 Web API 应用程序。

var data = new Data
            {
                Key = "k1",
                Value = 80
            };

IClient httpClient = new FluentClient("http://localhost:46551/");
var x = httpClient.PostAsync("weatherforecast", data).GetAwaiter().GetResult();

对于两个 Web API 应用程序,我的模型 class 低于 Valueobject 类型的位置,这是我的硬性要求,我不能接受实际类型。

public class Data
{
    public string Key { get; set; }
    public object Value { get; set; }
}

当我将数据发布到 ASP.NET Web API 2(使用 .Net 4.6.1)时,VS 调试器仅正确显示值而没有任何其他负载:

但对于 ASP.NET Core 3.1 Web API,VS 调试器显示如下,与 ValueKind:

完全不同的表示

我需要将 data 写入 Json 格式,输出低于预期,

{ "Key":"k1", "Value":80 }

当我尝试为 ASP.NET Core 3.1 Web API 序列化 data 时,我得到了这个输出:

var ser = JsonConvert.SerializeObject(data);

{ "Key":"k1", "Value": {"ValueKind":4} }

对于 ASP.NET Web API 2 应用程序,虽然我得到了预期的输出。

问题,如何从 ASP.NET Core 3.1 应用程序获得此输出 { "Key":"k1", "Value":80 } 以及为什么两个应用程序的行为不同?

谢谢,

您以前使用过 Newtonsoft 吗? JSON 格式化程序现在包含在 netcore 3x 中是默认的,除非您明确包含另一个解析器,例如 NewtonSoft。 new/default 解析器的行为与 Newtonsoft 有很多不同,但在迁移时让我的团队最痛苦的是 System.Text.Json 解析器在识别 JSON 时不做假设. 这是最常见的情况,有时一个字段有时可能是一个复杂的 JSON 对象,并且在诸如布尔值或整数的情况下还包含原始类型。对我来说,一个具体的例子是一个设置概念,它基本上是一个 key/value 对,其中键是设置的名称,例如 GridSettings,它是一个 blob 并作为 JSON 存储在 Postgres 中,但是另一个设置是这样的因为 showHidden 是简单的 true 或 false。 Newtonsoft 仍然会将该布尔值强制转换为 JSON,因为支持模型和实体模型将其声明为 System.Text.Json 表示不,除非您另有说明,否则这只是一个布尔值。

尝试在 IoC/Startup 中注入 Newtonsoft 作为解析器,看看是否会改变行为。

关于新解析器差异的一些细节: https://docs.microsoft.com/en-us/dotnet/core/compatibility/aspnetcore#authentication-newtonsoftjson-types-replaced

我们还必须在某些情况下对格式化程序进行调整:

自定义格式化程序: https://code-maze.com/content-negotiation-dotnet-core/

总而言之,我确实认为不做任何假设的解析器意味着很好并且可能是一件好事。然而,就我而言,我们根本没有准备好进行所有必要的修正来抵消这种变化。因此现在,我们坚持使用旧的 Newtonsoft。