为 ASP.NET Core MVC 显示 404 Not Found 页面

Posted

技术标签:

【中文标题】为 ASP.NET Core MVC 显示 404 Not Found 页面【英文标题】:Displaying a 404 Not Found Page for ASP.NET Core MVC 【发布时间】:2015-07-24 09:10:10 【问题描述】:

我正在使用下面的中间件为 HTTP 状态代码 400 到 599 设置错误页面。因此访问/error/400 会显示 400 Bad Request 错误页面。

application.UseStatusCodePagesWithReExecute("/error/0");

[Route("[controller]")]
public class ErrorController : Controller

    [HttpGet("statusCode")]
    public IActionResult Error(int statusCode)
    
        this.Response.StatusCode = statusCode;
        return this.View(statusCode);
    

但是,访问 /this-page-does-not-exist 会导致一个通用的 IIS 404 Not Found 错误页面。

有没有办法处理不匹配任何路由的请求?在 IIS 接管之前如何处理此类请求?理想情况下,我想将请求转发给/error/404,以便我的错误控制器可以处理它。

在 ASP.NET 4.6 MVC 5 中,我们必须使用 Web.config 文件中的 httpErrors 部分来执行此操作。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" />
      <error statusCode="404" responseMode="ExecuteURL" path="/error/404/" />
    </httpErrors>
  </system.webServer>
</configuration>

【问题讨论】:

您可以使用 global.asax 和 protected void Application_Error(object sender, EventArgs e) 捕获所有错误,然后从那里重定向。您需要检查它是否是 IsAjaxRequest,否则您可以根据异常重定向 这是 ASP.NET 5 Beta 7 MVC 6。没有 Global.asax。 真的吗?你确定吗?当您没有必须时,这是否像您“不得不使用”httpErrors?默认没有global.asax,加一个就行了——***.com/questions/24718640/… 我正在寻找一种内置的 ASP.NET 5 方法来执行此操作(如果有的话)。 ASP.NET 5 仍然需要一个 web.config 文件(以启用 GZip 压缩等),所以我宁愿使用它而不是 Global.asax。 找到了这个相关的问题,但不确定它是否真的回答了这个问题***.com/questions/29421164/mvc-6-404-not-found 【参考方案1】:

我发现的最好的教程之一是:https://joonasw.net/view/custom-error-pages

总结在这里:

1。 首先添加一个像ErrorController 这样的控制器,然后添加这个动作:

[Route("404")]
public IActionResult PageNotFound()

    string originalPath = "unknown";
    if (HttpContext.Items.ContainsKey("originalPath"))
    
        originalPath = HttpContext.Items["originalPath"] as string;
    
    return View();

注意:您可以将操作添加到另一个现有控制器,例如 HomeController

2。 现在添加PageNotFound.cshtml 视图。像这样的:

@
    ViewBag.Title = "404";


<h1>404 - Page not found</h1>

<p>Oops, better check that URL.</p>

3。 重要的部分就在这里。将此代码添加到Startup 类中,在Configure 方法中:

app.Use(async (ctx, next) =>

    await next();

    if(ctx.Response.StatusCode == 404 && !ctx.Response.HasStarted)
    
        //Re-execute the request so the user gets the error page
        string originalPath = ctx.Request.Path.Value;
        ctx.Items["originalPath"] = originalPath;
        ctx.Request.Path = "/error/404";
        await next();
    
);

请注意,必须在路由配置(如app.UseEndpoints...)之前添加。

【讨论】:

非常重要的注意:必须在路由配置之前添加,如 app.UseEndpoints 此答案中缺少的另一个重要内容,在错误控制器中,添加“[Route("error")]" 还要确保在此之前没有 app.Use()。【参考方案2】:

基于this SO item,IIS 在到达UseStatusCodePagesWithReExecute 之前获取404(并因此对其进行处理)。

你试过这个:https://github.com/aspnet/Diagnostics/issues/144?它建议终止收到 404 的请求,这样它就不会去 IIS 处理。这是添加到您的 Startup 的代码:

app.Run(context =>

   context.Response.StatusCode = 404;
   return Task.FromResult(0);
);

这似乎是一个仅限 IIS 的问题。

【讨论】:

这行得通,但是当我尝试将application.UseStatusCodePagesWithReExecute("/error/0"); 与此代码结合使用时,我总是收到 404 错误。有什么方法可以将两者结合起来吗? 嗨@MuhammadRehanSaeed,基于this,App.Run() 是一个包罗万象的接口,当调用链中没有其他任何东西处理请求时触发。因此,如果每个请求都返回 404,那么您的 Startup.cs 可能还有其他问题。上面的代码应该在 Startup 的末尾。 @MuhammadRehanSaeed,上面的代码适用于我所做的测试,UseStatusCodePagesWithReExecute 使用与您相同的ErrorController。在我的启动中,我依次拥有这些:app.UseStatusCodePagesWithReExecute()app.UseMvc()、上面的app.Run() 块,尽管改变前两个的顺序并不重要。它仅在不存在的资源上返回 404 自定义错误页面。 感谢 Frank,我发现 UseStatusCodePagesWithReExecute 必须在 UseMvc 之前才能工作。【参考方案3】:

您可以在 asp.net core 中的 EndPoint 中使用后备,如下所示(在 app.UseEndpoints 内)和剃须刀页面(NotFound 是 Pages 文件夹中的剃须刀页面,而不是控制器)

 endpoints.MapRazorPages();
            
 endpoints.MapFallback( context => 
    context.Response.Redirect("/NotFound");
    return Task.CompletedTask;
  );

【讨论】:

【参考方案4】:

Asp.net 核心 3.1 和 5

在您的HomeController.cs 中:

public class HomeController : Controller

   [Route("/NotFound")]
   public IActionResult PageNotFound()
   
      return View();
   

Startup.cs > ConfigureServices 方法中:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

   app.Use(async (context, next) =>
   
      await next();
      if (context.Response.StatusCode == 404)
      
         context.Request.Path = "/NotFound";
         await next();
      
   );
   
   app.UseHttpsRedirection();
   app.UseStaticFiles();

【讨论】:

【参考方案5】:

在处理 500 和 404 错误几个小时后,我实现了以下给定的解决方案。

要处理500 服务器端错误,您可以使用app.UseExceptionHandler 中间件,但app.UseExceptionHandler 中间件仅处理未处理的异常,而404 不是异常。为了处理404 错误,我设计了另一个自定义中间件,它检查响应状态代码,如果是404,则将用户返回到我的自定义404 错误页面。

if (env.IsDevelopment())
   
       app.UseDeveloperExceptionPage();
   
   else
   
       //Hnadle unhandled exceptions 500 erros
       app.UseExceptionHandler("/Pages500");
       //Handle 404 erros
       app.Use(async (ctx, next) =>
       
           await next();
           if (ctx.Response.StatusCode == 404 && !ctx.Response.HasStarted)
           
               //Re-execute the request so the user gets the error page
               ctx.Request.Path = "/Pages404";
               await next();
           
       );
   

注意:您必须在Configure 方法的开头添加app.UseExceptionHandler("/Pages500"); 中间件,以便它可以处理来自所有中间件的异常。自定义中间件可以放在app.UseEndpoins 中间件之前的任何件上,但最好放在Configure 方法的开头。 /Pages500/Pages404 网址是我的自定义页面,您可以为您的应用程序设计。

【讨论】:

以上是关于为 ASP.NET Core MVC 显示 404 Not Found 页面的主要内容,如果未能解决你的问题,请参考以下文章