.NET 8中Asp.Versioning无法兼容小版本号(.0)问题排查
问题描述
我们使用.NET 8开发,原已弃用Microsoft.AspNetCore.Mvc.Versioning,现迁移至以下两个包:
PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
调试模式下API路径http://localhost:7001/api/v1/NameController/ActionMethod可正常访问,但部署后http://localhost:7001/api/v1.0/NameController/ActionMethod返回404错误。现有大量客户端需同时使用v1和v1.0版本,必须确保两个路径均可用。
附上相关代码:
Startup.cs
services.AddEndpointsApiExplorer(); services.AddApiVersioning(config => { config.ReportApiVersions = true; config.ApiVersionReader = ApiVersionReader.Combine( new UrlSegmentApiVersionReader()); }).AddMvc() .AddApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; });
Controller代码
[ApiVersion("1.0")] [ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] [ApiExplorerSettings(GroupName = "v1")] [ApiController] public class NameController { [MapToApiVersion("1.0")] [HttpPost("ActionMethod")] public ActionMethod(parameters) { } }
请问哪里配置错误导致该问题?
问题分析与解决
核心问题是API版本的解析和路由匹配规则未同时兼容v1(简洁版)和v1.0(完整版)格式,具体修复点如下:
1. 启用版本号的宽松解析规则
默认的UrlSegmentApiVersionReader只会严格匹配版本格式,需配置宽松解析让v1和v1.0等价。修改AddApiVersioning配置:
services.AddApiVersioning(config => { config.ReportApiVersions = true; // 允许未指定版本的请求(按需开启) config.AllowUnspecifiedApiVersion = true; // 设置默认版本为1.0 config.AssumeDefaultVersionWhenUnspecified = true; config.DefaultApiVersion = new ApiVersion(1, 0); // 配置UrlSegmentReader支持宽松版本解析 config.ApiVersionReader = new UrlSegmentApiVersionReader { ParseOptions = new ApiVersionParserOptions { AllowMajorVersion = true, // 允许仅指定主版本(如v1) AllowMinorVersion = true, // 允许指定完整版本(如v1.0) AllowPrefix = true } }; }).AddMvc() .AddApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; });
2. 修正Controller的ApiExplorer分组约束
Controller上硬编码的[ApiExplorerSettings(GroupName = "v1")]仅对应v1格式,未包含v1.0,导致API文档和路由匹配遗漏该版本。两种修复方式:
- 方式1:移除硬编码分组,让ApiExplorer自动根据版本生成对应分组:
[ApiVersion("1.0")] [ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] [ApiController] public class NameController { [MapToApiVersion("1.0")] [HttpPost("ActionMethod")] public ActionMethod(parameters) { } } - 方式2:添加多分组(如果需要手动指定):
[ApiExplorerSettings(GroupName = "v1")] [ApiExplorerSettings(GroupName = "v1.0")]
3. 检查部署环境的路由规则
部署环境(如IIS、反向代理)可能对URL中的小数点有特殊处理,需确保:
- IIS未启用拦截包含小数点路径段的请求过滤规则
- 反向代理的重写规则未修改
v1.0这类路径
验证修复效果
修改完成后,分别测试以下路径,确认均能正常响应:
http://localhost:7001/api/v1/NameController/ActionMethodhttp://localhost:7001/api/v1.0/NameController/ActionMethod
内容的提问来源于stack exchange,提问作者Vrinda
相关产品推荐
相关产品推荐

