UseStatusCodePagesWithReExecute 执行原始请求两次,没有针对 NotFound 结果的错误响应

UseStatusCodePagesWithReExecute executes original request twice without error response for NotFound results

我在 dotnet razor 页面网络应用程序中遇到 UseStatusCodePagesWithReExecute 问题,同时尝试为 return NotFound 结果的页面请求显示自定义 404 错误页面。具体来说,如果我 return 来自 OnGet 方法的 NotFound 我发现再次调用相同的请求并且永远不会重新执行提供给中间件的路径。

我使用的是 .NET Core 3.0,所以没有尝试过以前的版本或 3.1 预览版。

我已经通过简单的重现成功地重现了这个问题。以下将允许无效路由重定向到错误页面(例如 https://localhost:5001/foo),但是,路由 https://localhost:5001/ 将被调用两次并且不会重定向到错误页面。

所以我要问的问题是,这是一个错误还是我在这里遗漏了一些概念?我已经尝试了相关的 UseStatusCodePagesWithRedirects 方法,它按照它说的去做,但如果可以的话,我真的很想使用 ReExecute。

复制

环境:

步骤:

  1. 创建模板剃刀项目dotnet new webapp -n myapp
  2. 编辑 Index.cshtml.cs OnGet 方法如下:
        public IActionResult OnGet()
        {
            return NotFound();
        }
  1. 编辑 Startup.cs 并在 Configure 方法中的 if/else 代码块之后添加 app.UseStatusCodePagesWithReExecute("/Error");,如下所示:
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            // Added this line
            app.UseStatusCodePagesWithReExecute("/Error");

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
  1. 在第一行的 OnGet 中放置一个断点(假设 VSCode 或 Visual Studio 2019)。
  2. 运行 调试并 F5 将第一个请求传递到索引页面。没有重定向到 /Error,而是再次命中断点。
  3. 再次按 F5,然后浏览器显示其标准 404 而不是错误页面。

提前致谢。

StatusCodePages 中间件有 3 个方法来显示自定义错误页面,它们是 UseStatusCodePagesUseStatusCodePagesWithReditectsUseStatusCodePagesWithReExecute。如果您想通过编辑 Index.cshtml.cs OnGet 方法在每次访问 https://localhost:5001/ 时获得 return NotFound 结果,您应该使用 UseStatusCodePages 来自定义您的 404错误页面而不是 UseStatusCodePagesWithReExecute.

不过,如果你坚持使用UseStatusCodePagesWithReExecute,你就不需要return一个真正的NotFoundUseStatusCodePagesWithReExecute 用于不存在的资源。一旦您访问 https://localhost:5001/any-non-exisisting-page, it will throw 404 and then re-execute a request for your own error page. But it's not a replacement of NotFound method. At the same time, pay attention to some conditions and restriction when using UseStatusCodePagesWithReExecute, you can refer to this article: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-3.1 .

这是一个工作示例。

  1. 编辑Startup.cs配置方法,像这样:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
        //app.UseDeveloperExceptionPage();
        }
        else
        {
       // app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for 
        production scenarios, see https://aka.ms/aspnetcore-hsts.
       // app.UseHsts();
        }
    
       //app.UseStatusCodePages();
        app.UseStatusCodePagesWithReExecute("/Error", "?code={0}");
       // app.UseHttpsRedirection();
    
        app.UseStaticFiles();
    
        //app.UseStatusCodePagesWithRedirects("/Error");
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    
    }
    
  2. 将@page "{code?}" 添加到 Error.cshtml:

@page "{code?}"
@model ErrorModel
@{
    ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h1 class="text-danger">Status Code: @Model.ErrorStatusCode</h1>

<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
    <p>
        <strong>Request ID:</strong> <code>@Model.RequestId</code>
    </p>
}

<h3>Development Mode</h3>
<p>
    Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
    It can result in displaying sensitive information from exceptions to end users.
    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
    and restarting the app.
</p>

  1. 当访问https://localhost:52602/hhh时,在Edge中是一个不存在的页面,浏览器显示这个页面:

如果你使用

return new NotFoundResult();

而不是

return NotFound();

它将使用所需的管道,唯一的缺点是无法传递消息,如果要传递消息,则需要构建自己的中间件来处理这种情况。