在 ASP.NET Core 中优雅地实现 API 版本控制

在构建 Web API 的过程中,随着功能迭代和架构升级,接口不可避免地会发生变更。
为了确保系统的稳定性与兼容性,合理使用 API 版本控制(API Versioning) 是至关重要的。

图:ASP.NET Core API 版本控制架构概览

⚠️ 注意:Microsoft.AspNetCore.Mvc.Versioning 已被弃用,推荐使用其作者维护的新库 Asp.Versioning.Mvc,它继承了原有功能并进行了增强支持,适用于 .NET 6 及更高版本。


🧩 配置 API 版本控制策略

// Configure API versioning with multiple versioning strategies
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new Asp.Versioning.ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;

    // Combine multiple versioning methods
    options.ApiVersionReader = ApiVersionReader.Combine(
        new QueryStringApiVersionReader("version"),     // ?version=1.0
        new UrlSegmentApiVersionReader(),               // /v1.0/controller
        new HeaderApiVersionReader("X-API-Version"),    // X-API-Version: 1.0
        new MediaTypeApiVersionReader("version")        // Accept: application/json;v=1.0
    );
}).AddMvc();

📌 说明:

  • • UrlSegmentApiVersionReader 的优先级最高。

  • • 支持多种方式混合使用,提高客户端调用灵活性。


📦 Swagger 集成配置

builder.Services.AddSwaggerGen(options =>
{
    // Define Swagger documents for each version
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "MyAPIv1",
        Description = "API 文档: 版本 1"
    });

    options.SwaggerDoc("v2", new OpenApiInfo
    {
        Version = "v2",
        Title = "MyAPIv2",
        Description = "API 文档: 版本 2"
    });

    // Resolve conflicting actions by selecting the first one
    options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

    // Optional: automatically group APIs by version
    options.DocInclusionPredicate((version, apiDescription) =>
    {
        var model = apiDescription.ActionDescriptor as ControllerActionDescriptor;
        return model?.ControllerTypeInfo.GetCustomAttributes(true)
            .OfType<ApiVersionAttribute>()
            .SelectMany(attr => attr.Versions)
            .Any(v => $"v{v}" == version) ?? false;
    });
});
app.UseSwaggerUI(options =>
{
    // Assign endpoints for each version in Swagger UI
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPIv1");
    options.SwaggerEndpoint("/swagger/v2/swagger.json", "MyAPIv2");
});

✅ 实现方式汇总

📍 方式一:通过 URL 路径进行版本控制

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
publicclassUsersController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 1.0");
}

[ApiController]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
publicclassUsersV2Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 2.0");
}

请求示例:

GET /api/v1.0/users
GET /api/v2.0/users

📍 方式二:通过查询参数进行版本控制

[ApiController]
[ApiVersion("1.0")]
[Route("api/[controller]")]
publicclassUsersController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 1.0");
}

[ApiController]
[ApiVersion("2.0")]
[Route("api/[controller]")]
publicclassUsersV2Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 2.0");
}

请求示例:

GET /api/users?api-version=1.0
GET /api/users?api-version=2.0

📍 方式三:通过 HTTP 请求头进行版本控制

[ApiController]
[ApiVersion("1.0")]
[Route("api/[controller]")]
publicclassUsersController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 1.0");
}

[ApiController]
[ApiVersion("2.0")]
[Route("api/[controller]")]
publicclassUsersV2Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 2.0");
}

请求示例:

GET /api/users
Headers:
    X-API-Version: 1.0

📍 方式四:通过媒体类型(Accept 头)进行版本控制

[ApiController]
[ApiVersion("1.0")]
[Route("api/[controller]")]
publicclassUsersController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 1.0");
}

[ApiController]
[ApiVersion("2.0")]
[Route("api/[controller]")]
publicclassUsersV2Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 2.0");
}

请求示例:

GET /api/users
Headers:
    Accept: application/json;v=1.0

📊 各种方式对比分析

方式

优点

缺点

URL 路径

清晰直观,易于调试

不易迁移旧路径

查询参数

简单易用,对客户端透明

不够语义化

请求头

对客户端无侵入性

需要客户端配合设置 header

MediaType

符合 RESTful 设计规范

实现复杂,需处理 content negotiation


🔗 参考资料

  • • ASP.NET Core API 版本控制详解

  • • GitHub - Asp.Versioning.Mvc

  • • Swagger 官方文档

现在就开始为你的 API 添加版本控制吧!🚀


如果你觉得这篇文章对你有帮助,欢迎点赞、收藏并分享给更多开发者!让我们一起学习,共同进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值