asp.net core 6+ 原生支持 api 版本控制,通过 microsoft.aspnetcore.mvc.versioning 深度集成 mvc 管道,需在 program.cs 中调用 addapiversioning() 并显式配置版本发现方式(url/query/header),控制器与 action 必须显式标注 [apiversion],否则不参与版本协商。

ASP.NET Core 6+ 原生支持 API 版本控制,不用自己造轮子
ASP.NET Core 3.0 起官方就内置了 Microsoft.AspNetCore.Mvc.Versioning,6.0+ 更是深度整合进 MVC 管道。别再手写 Route 拼接版本号或靠自定义中间件判断 Accept 头——框架已提供稳定、可测试、可扩展的方案。
关键点:它不是“插件”,而是 MVC 的一部分,所有路由、模型绑定、过滤器、文档生成(如 Swagger)都能感知版本。
常见错误现象:404 Not Found 即使路由看起来匹配;InvalidOperationException: No API version was specified;Swagger 显示多个同名 endpoint 但无法区分版本。
- 必须在
Program.cs中调用AddApiVersioning(),且要在AddControllers()之后、BuildServiceProvider()之前 - 默认不启用任何版本发现方式,需显式配置(如 URL、Query String 或 Header)
- 控制器没加
[ApiVersion("1.0")],哪怕全局配置了默认版本,该 controller 也不会被版本系统识别
URL 路径版本(/api/v1/users)最直观,但要注意路由模板冲突
这是前端最易理解的方式,也是调试时最方便的。但它和传统 MVC 路由共存时容易踩坑。
使用场景:对外公开 API、需要明确语义、前端工程师能直接从 URL 判断行为边界。
参数差异:options.AssumeDefaultVersionWhenUnspecified = true 控制无版本请求是否走默认版;options.DefaultApiVersion = new ApiVersion(1, 0) 设定默认值;options.ReportApiVersions = true 会让响应头带上 api-supported-versions。
性能影响:几乎为零,只是路由匹配时多一个 segment 解析。
- 路由模板必须包含
api-version占位符,比如routes.MapControllerRoute("v1", "api/v{version:apiVersion}/[controller]") - 不要同时注册两个相似模板,例如
"api/{controller}"和"api/v{version:apiVersion}/{controller}"—— 后者会永远匹配失败,因为前者更“贪婪” -
[MapToApiVersion("2.0")]可用于将某个 action 显式映射到非当前 controller 默认版本,适合灰度迁移
Query String 版本(?api-version=2.0)适合快速验证,但不推荐生产环境
开发调试阶段最省事,改个参数就能切版本,不用动 URL 结构。但它暴露版本信息、无法被 CDN 缓存区分、也不符合 RESTful 对资源 URI 的语义要求。
常见错误现象:Swagger UI 不自动带 api-version 查询参数;Postman 手动加了却仍返回 v1 —— 很可能是没启用 QueryStringApiVersionReader。
- 启用方式是在
AddApiVersioning()里加.AddQueryStringApiVersionReader() - Query String 优先级低于 URL 路径,高于 Header;如果三者都传了,以路径为准
- 不能只靠 Query String 实现“强制版本协商”,因为客户端可能不传,而你又没设
AssumeDefaultVersionWhenUnspecified = false,结果就是400 Bad Request
Controller 和 Action 级版本声明必须显式标注,继承不自动传递
很多人以为给基类 Controller 加了 [ApiVersion("1.0")],子类就自动继承——不会。每个 controller 都得自己标,action 也一样。
使用场景:同一业务模块分版本迭代(如用户注册逻辑 v1 用邮箱,v2 支持手机号+验证码),需并行维护。
兼容性影响:不同版本的 controller 可以共存于同一程序集,只要 route 和 verb 不冲突;Swagger 会按版本分组展示。
- 一个 controller 可标注多个版本:
[ApiVersion("1.0"), ApiVersion("2.0")],对应 action 用[MapToApiVersion("2.0")]绑定 - 若某 action 只属于 v2,但 controller 标了 v1 和 v2,就必须加
[MapToApiVersion("2.0")],否则 v1 请求也能访问到它 - 别用
[ApiVersionNeutral]除非真要排除版本控制(如健康检查 endpoint),它会绕过整个版本协商流程
最容易被忽略的是:API 版本控制不是“开关”,它是一整套协商链路——从路由匹配、服务解析、到文档生成,任何一个环节漏配,都会导致行为不符合预期。尤其是 Swagger 集成时,AddVersionedApiExplorer() 和 AddSwaggerGen() 的调用顺序、以及 ConfigureApiVersioningOptions() 是否同步更新,经常让版本在 UI 上“消失”。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











