Связывать параметры запроса с моделью в ядре ASP.NET

Я пытаюсь использовать привязку модели к параметрам запроса к объекту для поиска.

Мой объект поиска

[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, свойство критериев в действии контроллера равно null. Однако я могу назвать конечную точку не как случай змеи .../users/search?firstName=dave, а свойство критериев содержит значение свойства. В этом случае Model Binding работало, но не тогда, когда я использую snake_case.

Как я могу использовать snake_case с привязкой к модели?

Ответ 1

Вам нужно добавить атрибут [FromQuery] к свойствам модели отдельно

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

Ответ 2

Решение для .net core 2.1, 2.2 и 3.0

Или без атрибутов вы можете сделать что-то вроде этого, что я считаю чище (конечно, если свойства модели совпадают с параметрами запроса).

Между тем я использую его в .net core 2.1, 2.2 и 3.0 Preview 5 & 6.

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

}

Ответ 3

Согласно ответу @Carl Thomas, вот более простой и неопрятно набранный способ иметь имя FromQuery в виде змеи:

CustomFromQuery

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

StringExtensions

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