.NET 5 AspNetCore catch-all 路由取代定义路由

.NET 5 AspNetCore catch-all route supersedes defined route

从 .NET Core 3.1 迁移到 .NET 5 时,我们遇到了包罗万象的路由配置的特殊行为。

启动配置的相关部分如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
                 name: "default",
                 pattern: "home",
                 defaults: new { controller = "Home", action = "Index" });

        //catch-all endpoint
        endpoints.Map("{*.}", async (t) =>
        {
            System.Console.WriteLine("hello");

            await Task.CompletedTask;
        });
    });
}

调用 url:http://localhost:port/home 命中了 catch-all 路由而不是家庭控制器。如果 catch-all 端点映射被注释掉,则家庭控制器端点被命中——这是我们在这两种情况下所期望的,阅读 MSDN 文档。迁移前的行为是首先调用最具体的路由(即家庭控制器端点),并且只有在没有匹配到路由时才响应。

.NET 5 中是否有重大变化,或者我们是否遗漏了什么?

  1. 您可以使用优先级来解决不匹配问题。此路由可以拾取任何其他路由未处理的 URL。

    [Route("{*url}", Order = 999)]
    public IActionResult CatchAll()
    {
    
       return View();
    }
    
  2. 在这种情况下,另一种方法是使用状态代码页。

    正在启动

             app.UseExceptionHandler(option=>
             {
                 app.UseStatusCodePagesWithReExecute("/error/{0}");
             });
    

    控制器

     [Route("error/404")]
     public IActionResult Error404()
     {
         return View();
     }
    

事实证明,该行为是由于 aspnetcore 团队在 5.0 中引入了对路由机制的更改 - 有问题的行为实际上是设计使然。

在此处查看更多信息:https://github.com/dotnet/aspnetcore/issues/29594