簡體   English   中英

多個可選參數,包括 ASP.NET Core Web API 路由中的枚舉類型

[英]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);
    }

我怎樣才能解決這個問題?

路由中不能有可選參數;

如果reportStatusisNecessary是可選的,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 綁定器

自定義 Model 綁定在 ASP.NET 內核中

自創建此問題以來已經有很長時間了,但我希望這對正在尋找相同問題的其他人有所幫助: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM