我正在尝试使用从查询参数到对象的模型绑定来进行搜索。
我的搜寻对象是
[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与模型绑定一起使用?
您需要单独向模型属性添加
[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)
{
}
对于像我一样从搜索引擎到达这里的人:
使其在 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 框架中已经提供的如此简单的事情来说,上面的答案太复杂了。
就我而言,我遇到了一个问题,我的参数名称是
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)
在 .NET 6 中,我需要将
[FromQuery]
添加到端点的参数,以及将 [FromQuery(Name="")]
添加到模型的每个属性。
我没有将 MVC 依赖添加到我的模型项目中,而是将服务模型变成了接口,并在 WebAPI 项目中创建了一个新模型,该模型可以使用注释并实现接口,因此我不需要创建/映射2 个型号。
根据 @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; }
}
如果
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; }
}
我不知道 .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