【问题标题】:Bind query parameters to a model in ASP.NET Core将查询参数绑定到 ASP.NET Core 中的模型
【发布时间】:2017-03-21 14:03:13
【问题描述】:

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

我的搜索对象是

[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,并且条件属性包含属性值。在这种情况下,模型绑定有效,但在我使用蛇形案例时无效。

如何将蛇形案例与模型绑定一起使用?

【问题讨论】:

标签: c# asp.net asp.net-mvc asp.net-core model-binding


【解决方案1】:

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

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

【讨论】:

  • 如果我想将数据合同与具有 GET 和 POST 端点的自定义名称的成员一起使用,那么在第一种情况下它将是 FromQuery,而 FromBody 用于 POST 请求?
  • 我无法让它工作,但它被标记为答案。
  • 我只想补充一点,我有一个其他人也可能遇到的问题:我将参数命名为“模型”。我的对象有一个也被命名为“模型”的属性。在我重命名参数之前,数据绑定不会起作用。
  • FromQuery 位于 Microsoft.AspNetCore.Mvc 包中,将此依赖项添加到仅存储 POCO 的项目中有点可悲。
  • @sander 的解决方案对我有用 - 谢谢我花了一个多小时试图解决这个问题。检查所有参数名称的经验教训。
【解决方案2】:

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

}

【讨论】:

  • 是的,它只适用于控制器方法中的 [FromQuery]
  • 这是 NetCore 2.1 及更高版本的正确答案,接受的答案是不合时宜的。
  • 这应该是被接受的答案,或者恰好是被接受的答案的 OP 应该更新他们的答案。
  • 我认为问题在于这个答案没有解决问题的细节。正如给出此答案的人所说,OP 特别要求该属性使用不同的名称,这不支持这一点。
  • 我使用的是 .net core 2.2,这种方法对我不起作用。但是,接受的答案确实如此。
【解决方案3】:

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

让它在 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,所以基本上你必须在两个地方使用FromQuery。 对于 asp.net 框架中已经提供的这么简单的东西,以上答案恕我直言太复杂了。

【讨论】:

  • 它也适用于您的属性上的[JsonPropertyName("otherName")]。因此,我假设它也适用于 Newtonsoft.JSON 注释(但没有尝试)。所以你可以在你的方法中指定[FromQuery],并且在需要时仍然可以在 Body 中使用相同的对象(无需额外的注释)。不需要这么具体。
  • @Max - 嗨,Max。不,它不适用于 Newtonsoft [JsonPropery(Name = "otherName")]
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    根据@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])", "$1_$2").ToLower();
    }
    

    用法

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

    【讨论】:

      【解决方案6】:

      如果 public async Task&lt;IActionResult&gt; Get([FromQuery] RequestDto request);

      不适用于任何人,您可以尝试[FromRoute]

      public async Task&lt;IActionResult&gt; Get([FromRoute] RequestDto request);.

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        • 2016-12-15
        • 1970-01-01
        • 1970-01-01
        • 2020-11-09
        • 2022-06-11
        相关资源
        最近更新 更多