如何针对我的场景在 ASP.NET Core 6 Web API 中设置默认版本控制?

问题描述 投票:0回答:3

刚刚意识到我对 ASP.NET Core 6 Web API 版本控制的理解是错误的。

这是我的控制器:

[ApiVersion("1.0")]
[ApiController]
[Authorize]
public class FundController 
{
    [MapToApiVersion("1.0")]
    [Route("/Fund/v{version:apiVersion}/delta")]
    public async Task<List<PortfolioHolding<Holding>>> Delta([FromQuery] Request dataModel)
    {
    }
}

我想要的是支持路线

/Fund/v1.0/delta
/Fund/delta
,当消费者未提供版本控制时(例如调用
/Fund/delta
),将使用默认版本。

所以我像这样配置了版本控制。但是,当我调用

/Fund/delta
时,我收到 http 404 错误。

但是

/Fund/v1.0/delta
会击中正确的控制器。

我做错了什么?

services.AddApiVersioning(option =>
        {
            option.DefaultApiVersion = new ApiVersion(1, 0);
            option.AssumeDefaultVersionWhenUnspecified = true;
            option.ReportApiVersions = true;
        });
asp.net-core-webapi asp.net-web-api-routing asp.net-core-6.0
3个回答
1
投票

问题是你没有在控制器中指定路由。

您应该添加默认路由以及格式化版本路由。然后,您应该确保您的端点具有 MapToApiVersion 属性中指定的版本。

以下是控制器的代码示例:

[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("[controller]")]
[Route("[controller]/v{version:apiVersion}")]
public class FundController : ControllerBase
{
    [MapToApiVersion("1.0")]
    [Route("delta")]
    [HttpGet]
    public async Task<List<PortfolioHolding<Holding>>> DeltaV1([FromQuery] Request dataModel)
    {
    }

    [MapToApiVersion("2.0")]
    [Route("delta")]
    [HttpGet]
    public async Task<List<PortfolioHolding<Holding>>> DeltaV2([FromQuery] 
Request dataModel)
    {
    }
}

0
投票

另一种无需在每个控制器上都有

[Route("api/[controller")]
的方法是实现并使用 Asp.Versioning.Conventions

中的 IControllerConvention
internal class DefaultRouteHandler : IControllerConvention
{
    public bool Apply(IControllerConventionBuilder builder, ControllerModel controller)
    {
        var attributeModel = new AttributeRouteModel();
        var selectorModel = new SelectorModel();

        attributeModel.Template = "api/[controller]";
        selectorModel.AttributeRouteModel = attributeModel;
        controller.Selectors.Add(selectorModel);

        return true;
    }
}

然后在你的主要...

services.AddApiVersioning(option =>
        {
            option.DefaultApiVersion = new ApiVersion(1, 0);
            option.AssumeDefaultVersionWhenUnspecified = true;
            option.ReportApiVersions = true;
        })
        .AddMvc(option => option.Conventions.Add(new DefaultRouteHandler()));

为了防止 Swagger 显示重复的(版本+默认)路由,您可以执行类似的操作

builder.Services.AddSwaggerGen(x =>
    {
        x.DocInclusionPredicate((v, d) => d.RelativePath.Contains($"/{v}/", StringComparison.OrdinalIgnoreCase));
    });

0
投票

通常,这样做很容易。这种方法的缺点是您需要使用此属性手动更改 API 的“默认”版本

[ApiController]
[Route("api/v1/[controller]")]
[Route("api/[controller]")]
[ApiVersion("1.0")]
© www.soinside.com 2019 - 2024. All rights reserved.