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

image.png

图: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(10);
    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();
C#

📌说明:

  • 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;
    });
});

C#
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");
});

C#

实现方式汇总

📍方式一:通过 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");
}

C#

请求示例:

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

js

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

[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");
}
C#

请求示例:

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

📍方式三:通过 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");
}
C#

请求示例:

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

📍方式四:通过媒体类型(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");
}
C#

请求示例:

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

各种方式对比分析

方式 优点 缺点
URL 路径 清晰直观,易于调试 不易迁移旧路径
查询参数 简单易用,对客户端透明 不够语义化
请求头 对客户端无侵入性 需要客户端配合设置header
MediaType 符合 RESTful 设计规范 实现复杂,需处理 content negotiation

参考资料

• ASP.NET Core API 版本控制详解
• GitHub - Asp.Versioning.Mvc
• Swagger 官方文档