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

Bind query parameters to a model in ASP.NET Core

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

我的搜索对象是

[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 控制器操作的条件 属性 为空。 但是,我可以将端点称为 not snake case .../users/search?firstName=dave 并且条件 属性 包含 属性 值。在这种情况下,模型绑定有效,但在我使用 snake_case.

时无效

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

您需要将 [FromQuery] 属性单独添加到模型属性中

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

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

}

根据 @Carl Thomas 的回答,这里有更简单和强类型的方法来获得蛇形大小写 FromQuery 名称:

CustomFromQuery

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])", "_").ToLower();
}

用法

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

对于像我这样从搜索引擎来到这里的任何人:

使其在 asp.net 核心 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框架中已经提供的如此简单的事情,以上答案恕我直言太复杂了。

如果 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; }
}

在我的例子中,我遇到了一个问题,我的参数名称是 option,在我的 class 中,我还有一个名为 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)