[英]ASP.NET CORE Model binding: Why the getter of DTO is get called by runtime before the value is set?
我正在尝试使用getter来验证DTO的属性,如果属性无效则抛出异常,示例代码如下:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpPost("test")]
public IActionResult Post([FromBody] Foo f)
{
return Ok(f.Bar.Count == 1);
}
}
public class Foo
{
private List<string> _bar;
public List<string> Bar
{
get
{
if (_bar == null || _bar.Count == 0) throw new System.Exception("at lease one element is required!");
return _bar;
}
set
{
_bar = value;
}
}
}
使用 curl 调试 api
curl --location --request POST 'http://localhost:5000/WeatherForecast/test2' --header 'Content-Type: application/json' --data-raw '{
"Baz":"HelloWorld"
}'
在 API 调试过程中,我观察到 setter 是用一个空的 list 值调用的,即使相应的输入有值,然后是 getter。 结果,由于列表为空,getter 引发了异常。
似乎 model 绑定行为在enumerable
类型和non-enumerable
类型之间存在一些差异(如果我将Bar
从List<string>
更改为string
,我将在 setter 中获得值);
问题:
non-enumerable
enumerable
类型的属性,我想在getter而不是其他地方进行验证 在您的请求 model Foo
中,您断言Bar
将是字符串的集合(例如,数组)。 但是,在您的 curl 请求中,您将Bar
设置为单个字符串,而不是包含一个字符串的数组。
相反,您应该使用curl --location --request POST 'http://localhost:5000/WeatherForecast/test2' --header 'Content-Type: application/json' --data-raw '{ "Bar": ["HelloWorld"] }'
。
如果您想接受Bar
的字符串或数组,则不能将 DTO class 与[FromBody]
一起使用。 相反,您必须编写自己的逻辑来确定请求正文中的数据类型,然后手动将 JSON 数据解析为适当的 model。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.