如何将JSON主体属性映射为带有验证的.net Core web API动作方法的动态参数?



我必须构建一个。net Core REST API,并且我有大约24个端点可以接受简单的JSON对象,例如:-

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

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

等。

一些属性,如上面的foo,在几个端点中是常见的,但具有不同的验证要求。在一些端点,它们是必需的,在另一些端点,它们不是,等等。我无法更改这些JSON有效负载,因为它们是由我无法控制的第三方生成的。

如何将这些参数直接映射到。net Core API方法中的端点,而不需要类?

当然,我可以为每个端点创建一个类,例如
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; }
}
...

注意不同的验证规则。

但是我不想创建二十多个类。我更愿意直接在endpoint方法中指定它们:

[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)
{
...
}

只需查看方法,就可以更容易地阅读和确定需要哪些属性以及何时需要哪些属性,而不是打开24个类似命名的类文件中的一个,或者打开一个包含24个具有相同名称属性的类似命名的类的文件。

那么我怎么能得到。net Core解析JSON并分配属性值给动作方法参数?

我不知道这个问题的直接答案,所以我将根据您的声明"用另一种方法作为XY问题的答案来回答这个问题;通过查看方法">,阅读和找出需要哪个属性以及何时需要。

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

通过向端点方法和输入模型类添加XML文档,您还打开了使用Swashbuckle添加Swagger页面的简单路径,这将为您提供一种简单的方法来检查模型值类型是什么以及哪些是必需的,等等,以及Swagger页面本身中的示例JSON主体,其中包含关于所有参数目的的完整文档。

当你最终得到一堆模型类时,它只是一个按钮,从Visual Studio跳到你的类,看到你的验证需求和输入类型,同时"在代码中"。如果类生成令人沮丧,您可以快速将JSON示例放入在线类生成器中,并获得"相当不错"的类生成器。输入模型的起始点:https://json2csharp.com/