如何将 JSON 正文属性映射为具有验证功能的 .NET Core web API 操作方法的动态参数?

How can I map JSON body properties as dynamic parameters of a .NET Core web API action method with validation?

我必须构建一个 .NET Core REST API 并且我有大约两打端点接收简单的 JSON 对象,例如:-

{
  "foo": 23,
  "bar": "bar_value"
}

{
  "foo": 12,
  "baz": true
}

等等

某些属性(例如上面的 foo)在多个端点中是通用的,但具有不同的验证要求。在某些端点中,它们是必需的,在其他端点中,它们不是,依此类推。我无法更改这些 JSON 有效负载,因为它们是由我无法控制的第三方生成的。

如何在没有 class 的情况下直接将这些参数映射到 .NET Core API 方法中的端点?

我当然可以为每个端点创建一个class,例如

public class SomeObject
{
    [Required]
    [Range(0, 100)]
    public int? Foo { get; set; }
    
    public string bar { get; set; }
}


public class SomeOtherObject
{
    public int? Foo { get; set; }
    
    [Required]
    public bool Baz { get; set; }
}

...

注意不同的验证规则。

但我不想创建两打 classes。我更愿意直接在端点方法中指定它们:

[HttpPut]
[Route("/some-route")]
public IActionResult SomeAction([Required, Range(0, 100)] int? foo, byte? bar)
{
    ...
}

[HttpPut]
[Route("/some-other-route")]
public IActionResult SomeOtherAction(int? foo, [Required] baz)
{
    ...
}

阅读和弄清楚需要哪些 属性 以及何时需要更容易,只需查看方法而不是打开两个名称相似的 class 文件中的一个或打开一个包含两打名称相似的 class 具有相同名称属性的文件。

那么如何让 .NET Core 解析 JSON 并将 属性 值分配给操作方法参数?

我不知道这个问题的直接答案是指定的,所以我会根据你的陈述用另一种方法作为 XY 问题来回答这个问题“这会容易得多阅读并找出需要哪些 属性 以及何时通过查看方法.

假设如果您使用 classes,则没有简单的方法来记录您自己的 API 表面积。在您的示例中,您已经在方法签名本身中编写了大量逻辑,更不用说默认值等的潜在行为,这会使这些签名逐渐难以阅读和理解,而这正是输入模型classes和模型验证旨在帮助封装。此外,既然您已经将模型分解成多个部分,那么无论是否可以完成,将验证问题作为一个内聚模型来处理都会变得越来越复杂。通过一次接受整个对象,您可以 运行 ModelState.IsValid 检查、汇总错误,或者添加您自己的并快速 return 来自控制器的错误。

By adding XML documentation to your endpoint methods and input model classes, you also open up the easy path of adding a Swagger page with Swashbuckle,这将为您提供一种简单的方法来检查模型值类型是什么以及需要哪些类型等,以及 Swagger 中的示例 JSON 主体页面本身包含关于所有参数用途的完整文档。

虽然您最终得到了一堆模型 classes,但只需在 Visual Studio 之外按下按钮即可跳转到您的 class 并查看您的验证要求和输入“在代码中”时键入。如果 class 生成令人沮丧,您可以快速将 JSON 样本放入在线 class 生成器并获得输入模型的“相当不错”的起点:https://json2csharp.com/