You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core从2.1升级到3.1/5后自定义路由匹配抛出ArgumentOutOfRangeException

问题根因

.NET Core 3.0+ 更换了全新的DFA路由匹配引擎,在处理同一路由段内包含多个参数+固定字面量的复杂路由场景时,匹配逻辑和2.1版本的旧路由引擎存在差异:引擎会按路由注册顺序依次尝试匹配所有符合路径层级的路由,你当前的场景中,访问/MyPath/my-slug/s1时引擎会先尝试匹配先注册的MyCustomRoute1的第三段规则m{id1}s{id2},解析过程中计算参数长度出错,直接抛出ArgumentOutOfRangeException异常,没有走到后续的MyCustomRoute2匹配逻辑。

解决方案

可根据你的项目情况选择以下任意一种方案:

  • 方案1(最简便,无侵入):调整两条路由的注册顺序,将规则更精准、段长度更短的MyCustomRoute2放在MyCustomRoute1之前注册。路由系统按注册顺序优先匹配,访问s1结尾的路径时会先命中MyCustomRoute2,不会触发MyCustomRoute1的解析逻辑,即可正常运行。
    修改后的注册代码示例:
    // 先注册更精准的短段路由
    endpoints.MapControllerRoute(
      name: "MyCustomRoute2",
      pattern: "MyPath/{slug}/s{id1}",
      defaults: new { controller = "home", action = "Index" },
      constraints: new { slug = "[a-z-]+", id1 = "[0-9]+" });
    
    // 再注册长段路由
    endpoints.MapControllerRoute(
      name: "MyCustomRoute1",
      pattern: "MyPath/{slug}/m{id1}s{id2}",
      defaults: new { controller = "home", action = "Index" },
      constraints: new { slug = "[a-z-]+", id1 = "[0-9]+", id2 = "[0-9]+" });
    
  • 方案2(兼容旧逻辑):如果不想改动现有路由注册顺序,可以回退到.NET Core 2.1的旧路由系统,在Startup.cs的ConfigureServices方法中添加如下配置即可:
    services.AddControllersWithViews()
      .AddMvcOptions(options => options.EnableEndpointRouting = false);
    
    注意该方案为兼容方案,不建议长期使用,旧路由系统后续版本可能会被移除。
  • 方案3(更稳定):改用属性路由配置规则,直接在对应的Controller Action上标注路由属性,属性路由优先级高于全局注册的路由,不会出现匹配顺序问题:
    public class HomeController : Controller
    {
        [Route("MyPath/{slug:regex([a-z-]+)}/m{id1:regex([0-9]+)}s{id2:regex([0-9]+)}", Name = "MyCustomRoute1")]
        [Route("MyPath/{slug:regex([a-z-]+)}/s{id1:regex([0-9]+)}", Name = "MyCustomRoute2")]
        public IActionResult Index(string slug, int id1, int? id2)
        {
            // 业务逻辑
        }
    }
    
    配置后删除Startup中对应的两条全局路由注册即可。

内容的提问来源于stack exchange,提问作者Beedjees

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 02:39:02