繁体   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