如果参数名称等于属性名称,则来自查询的 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 &lt;host&gt;/&lt;controller&gt;/search?term=abc&amp;caseInsensitive=true 调用 API,一切都会按预期工作 - Term 属性包含 "abc"CaseInsensitivetrue

这是有道理的,根据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 属性是 nullCaseInsensitive 是 @ 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 从表中选择条目,其中属性等于参数,否则选择 * 条目

VBA:如果工作簿中的工作表名称等于从用户窗体中选择的组合框值,则复制该工作表并将其粘贴到另一个工作簿中

几个SQL Server的查询题!

javascript-作用域-内存

Hibernate的增删改查操作