将查询参数绑定到 ASP.NET Core 中的模型

问题描述 投票:0回答:8

我正在尝试使用从查询参数到对象的模型绑定来进行搜索。

我的搜寻对象是

[DataContract]
public class Criteria 
{
  [DataMember(Name = "first_name")]
  public string FirstName { get; set; }
}

我的控制器有以下操作

[Route("users")]
public class UserController : Controller 
{
  [HttpGet("search")]
  public IActionResult Search([FromQuery] Criteria criteria)
  {
    ...
  }
}

当我如下调用端点时

.../users/search?first_name=dave
控制器操作上的条件属性为空。 但是,我可以不将端点称为蛇形情况
.../users/search?firstName=dave
并且 criteria 属性包含属性值。在这种情况下,模型绑定有效,但当我使用 Snake_case 时则无效。

如何将snake_case与模型绑定一起使用?

c# asp.net asp.net-mvc asp.net-core model-binding
8个回答
73
投票

您需要单独向模型属性添加

[FromQuery]
属性

public class Criteria
{
  [FromQuery(Name = "first_name")]
  public string FirstName { get; set; }
}

42
投票

.net core 2.1、2.2、3.0 和 3.1 的解决方案

或者没有属性,你可以做这样的事情,我认为这更干净(当然,如果模型属性与查询参数相同)。

同时我在.net core 2.1、2.2和3.0预览版和3.1中使用它。

public async Task<IActionResult> Get([FromQuery]ReportQueryModel queryModel) 
{ 

}

14
投票

对于像我一样从搜索引擎到达这里的人:

使其在 asp.net core 3.1+ 上运行

public async Task<IActionResult> Get([FromQuery] RequestDto request);

public class RequestDto
{
  [FromQuery(Name = "otherName")]
  public string Name { get; set; }
}

会将 json 属性

otherName
读入
RequestDto.Name
,所以基本上你必须在 2 个地方使用
FromQuery
。 恕我直言,对于 ASP.NET 框架中已经提供的如此简单的事情来说,上面的答案太复杂了。


2
投票

就我而言,我遇到了一个问题,我的参数名称是

option
并且在我的班级中我也有名为
option
的属性,因此它正在崩溃。

public class Content
{
    
    public string Option { get; set; }
    
    public int Page { get; set; }
}

public async Task<IActionResult> SendContent([FromQuery] Content option)

将参数更改为其他内容:

public async Task<IActionResult> SendContent([FromQuery] Content contentOptions)

2
投票

在 .NET 6 中,我需要将

[FromQuery]
添加到端点的参数,以及
[FromQuery(Name="")]
添加到模型的每个属性。

我没有将 MVC 依赖添加到我的模型项目中,而是将服务模型变成了接口,并在 WebAPI 项目中创建了一个新模型,该模型可以使用注释并实现接口,因此我不需要创建/映射2 个型号。


1
投票

根据 @Carl Thomas 的回答,这是使用蛇形案例 FromQuery 名称的更简单且强类型的方法:

自定义来自查询

public class CustomFromQueryAttribute : FromQueryAttribute
{
    public CustomFromQuery(string name)
    {
        Name = name.ToSnakeCase();
    }
}

字符串扩展

public static class ObjectExtensions
{
  public static string ToSnakeCase(this string o) => Regex.Replace(o, @"(\w)([A-Z])", "$1_$2").ToLower();
}

用法

public class Criteria
{
   [CustomFromQuery(nameof(FirstName))]
   public string FirstName { get; set; }
}

0
投票

如果

public async Task<IActionResult> Get([FromQuery] RequestDto request);

不适合任何人,你可以尝试[FromRoute]

public async Task<IActionResult> Get([FromRoute] RequestDto request);
.

在您的 dto 中,您必须保留 [FromQuery]

public class RequestDto
{
  [FromQuery(Name = "otherName")]
  public string Name { get; set; }
}

0
投票

我不知道 .NET 8 中发生了什么,或者这是否只是我的设置,但我无法像 @emery-noel 在他的答案或任何其他答案中所说的那样工作。

例如,这行不通:

[FromQuery]

[HttpGet]
public async Task<IActionResult> Agreements([FromQuery] ClientDocumentsParamsDTO parameters) { ...etc... }

也不起作用。我唯一的选择是要么做一些像这样丑陋的事情:

[AsParameters]

或者类似的东西,我猜,这是我没有尝试过的:

[HttpGet] public async Task<IActionResult> Agreements( [FromQuery(Name = "organizationid")] int OrganizationId, [FromQuery(Name = "account-class-id")] int? AccountClassId, [FromQuery(Name = "account-preference-id")] int? AccountPreferenceId, [FromQuery(Name = "account-category-id")] int? AccountCategoryId, [FromQuery(Name = "account-type-id")] int? AccountTypeId ) { ... etc...

我猜这与 
THIS

问题有关,但我不知道。

© www.soinside.com 2019 - 2024. All rights reserved.