[英]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.