[英]Multiple optional parameters including enum type in ASP.NET Core Web API routing
我正在我的 ASP.NET Core Web Api 中创建一个方法,该方法采用多个参数,所有这些参数都是可选的。 在 postman 上调用此方法时出现错误:
System.InvalidOperationException: The constraint reference 'StatusEnum' could not be resolved to a type. Register the constraint type with 'Microsoft.AspNetCore.Routing.RouteOptions.ConstraintMap'
如何在路由中使用枚举作为我的参数类型? 我的 controller:
[HttpPost("filter-reports/{reportStatus:StatusEnum?}/{IsNecessary:bool?}/{completionStatus: completionStatusEnum?}")]
[Authorize]
public ObjectResult GetDamageReportByFilters(StatusEnum? reportStatus, bool? IsNecessary, completionStatusEnum? completionStatus)
{
var result = _reportService.GetReportByFilters(reportStatus,IsNecessary, completionStatus);
return StatusCode(200, result);
}
我怎样才能解决这个问题?
路由中不能有可选参数;
如果reportStatus
和isNecessary
是可选的,url 会是什么样子?
../filter-reports/?/?/COMPLETED
?
从您的参数中制作一个 model 并将其发送到 post 方法的主体中,然后它们可以是可选的
您的问题是,通过希望将路由参数的值限制为枚举值,您使用了不正确的路由约束:您不能将枚举的名称用作路由约束(供参考,有效的路由约束列在此页面上)
您不需要指定约束来将路由参数标记为可选,只需使用问号即可:
[HttpPost("filter-reports/{reportStatus?}/{IsNecessary:bool?}/{completionStatus?}")]
[Authorize]
public ObjectResult GetDamageReportByFilters(StatusEnum? reportStatus, bool? IsNecessary, completionStatusEnum? completionStatus)
{
var result = _reportService.GetReportByFilters(reportStatus,IsNecessary, completionStatus);
return StatusCode(200, result);
}
请注意,由于没有路由约束,因此可以将任何值传递给 enum 参数。 如果这不是有效值,则传递给 function 的实际值为 0。如果 0 映射到有效枚举值,则使用该值,否则只需处理 0 值(在 C# 中,任何int
值可以存储在枚举中)。
如果您只想将值解析为 Enum object,那么您只需为每个 Enum 类型添加自定义 model 绑定器
自创建此问题以来已经有很长时间了,但我希望这对正在寻找相同问题的其他人有所帮助: https://nickheath.net/2019/02/20/asp-net-core-enum-route-约束/
我只是个性化:
namespace MyWebApp
{
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
public static partial class Extensions
{
public class CustomRouteConstraint<TEnum> : IRouteConstraint
where TEnum : struct, Enum
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
// retrieve the candidate value
var candidate = values[routeKey]?.ToString();
// attempt to parse the candidate to the required Enum type, and return the result
return Enum.TryParse(candidate, true, out TEnum _);
}
}
}
}
在startup.cs上:
public void ConfigureServices(IServiceCollection services)
{
//...
//! Enum route constraints: ref https://nickheath.net/2019/02/20/asp-net-core-enum-route-constraints/
services.Configure<Microsoft.AspNetCore.Routing.RouteOptions>(options =>
{
options.ConstraintMap.Add("MyCustomEnum", typeof(MyWebApp.Extensions.CustomRouteConstraint<Models.MyCustomEnum>));
});
//...
}
终于行动起来了:
[Route("/{area:MyCustomEnum}")]
public async Task<IActionResult> ViewAsync(MyCustomEnum area)
{
//...
}
一种更简单的方法(无需关心约束映射)是用实际枚举值的简单字符串/整数表示替换您方法的 StateEnum 参数,并将其作为参数的一部分在您的方法中解析。
[HttpPost("Test/{state}")]
public IActionResult TestMethod(string state)
{
if (!Enum.TryParse(state, true, out StateEnum stateEnumValue))
return BadRequest();
// Do stuff here
return Accepted();
}
[HttpPost("Test2/{state}")]
public IActionResult TestMethod2(int state)
{
StateEnum stateEnumValue = (StateEnum) state;
// Do stuff here
return Accepted();
}
public enum StateEnum
{
FirstState = 1,
SecondState = 2
}
但由于您的参数是可选的,您可以尝试使用 Query 字符串代替,允许您省略不需要的参数来请求。 或者(正如其他答案所建议的那样)使用代表您的参数的 pbject (因为在那里管理可选内容更容易)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.