如果参数名称等于属性名称,则来自查询的 ASP.NET Core Web API 复杂类型绑定不起作用
Posted
技术标签:
【中文标题】如果参数名称等于属性名称,则来自查询的 ASP.NET Core Web API 复杂类型绑定不起作用【英文标题】:ASP.NET Core Web API complex type binding from query does not work if parameter name equals property name 【发布时间】:2021-11-27 12:22:03 【问题描述】:我有一个 ASP.NET 核心 Web API 项目,控制器操作如下:
[HttpGet("search")]
public IEnumerable<string> Search([FromQuery] SearchDto dto)
// implementation
注意,操作参数dto
是一个复杂类型绑定来自查询。它看起来像这样:
public class SearchDto
public string Term get; set;
public bool CaseInsensitive get; set;
如果我使用 URL <host>/<controller>/search?term=abc&caseInsensitive=true
调用 API,一切都会按预期工作 - Term
属性包含 "abc"
和 CaseInsensitive
是 true
。
这是有道理的,根据https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-5.0#prefix--parameter-name,绑定首先尝试查找以参数名称为前缀的值(也就是在 URL 查询字符串中搜索键 "dto.Term"
和 "dto.CaseInsensitive"
),如果失败,它会尝试没有前缀的属性(又名。它在 URL 查询字符串中搜索 "Term"
和 "CaseInsensitive"
键)成功并绑定相应的值。
但是,如果我通过更改 dto
参数名称以匹配 DTO 类中的 Term
属性名称来稍微更改控制器操作,如下所示:
[HttpGet("search")]
public IEnumerable<string> Search([FromQuery] SearchDto term) // changed from 'dto' to 'term'
// implementation
然后绑定停止工作。使用与之前相同的 URL 调用 API 会导致调用控制器操作,但 DTO 属性未填充来自 URL 的值,而是具有默认值(又名。Term
属性是 null
和 CaseInsensitive
是 @ 987654340@)。
这是为什么呢?绑定应该像以前一样评估 - 键 "term.Term"
和 "term.CaseInsensitive"
在 URL 查询字符串中找不到,所以应该像以前一样尝试和匹配无前缀的名称,因此我希望绑定能够工作。这是一个错误还是我错过了什么?
这种天真无邪的变化完全打破了束缚,这似乎很奇怪。我们今天遇到了这种行为,很难弄清楚为什么绑定不再起作用了......
【问题讨论】:
【参考方案1】:如果你的行为会发生什么
[HttpGet("search")]
public IEnumerable<string> Search([FromQuery] string term)
是的,您是对的,您将毫无问题地获得“术语”值。现在您无法获取值,因为字符串类型无法转换为 SearchDto 类型。所以你得到空值。 Everytning 以应有的方式工作。当我在 Visual Studio 中测试您的问题时,我收到了关于可能不正确的模型绑定的警告。
“警告 MVC1004:‘SearchDto’类型的属性与参数‘term’同名。这可能导致模型绑定不正确。考虑重命名参数或使用模型绑定属性覆盖名称。”
你为什么没有在你的帖子中提到它?
【讨论】:
我在 VS 中没有看到任何关于可能不正确绑定 (v16.11.4) 的警告。根据链接的文档,在绑定复杂类型时,参数名称仅用作值搜索的前缀,如果未找到没有前缀的属性,则搜索不带前缀的属性,因此如果 URL 包含无前缀的属性名称,它应该与任何参数名称一起使用,对吧? 我真的很抱歉,但我不是教授,所以我不愿意参加“什么是对什么是错”的辩论。我想您可以将您的建议通过电子邮件发送给微软团队,并让我们知道结果。 我在 github 上提交了此文件,并将其标记为 bug github.com/dotnet/aspnetcore/issues/37360,尽管争论是是否应该修复或更好地记录它:D。 Visual Studio 中的警告不存在,因为分析器跳过了ApiController
,这是 web api 项目的情况。以上是关于如果参数名称等于属性名称,则来自查询的 ASP.NET Core Web API 复杂类型绑定不起作用的主要内容,如果未能解决你的问题,请参考以下文章
SQL 从表中选择条目,其中属性等于参数,否则选择 * 条目