为 ASP.NET 核心 MVC 显示 404 未找到页面
Displaying a 404 Not Found Page for ASP.NET Core MVC
我正在使用下面的中间件为 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 未找到错误页面。
有没有办法处理不匹配任何路由的请求?在 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>
基于 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 的问题。
我找到的最好的教程之一是: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
class,在 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...
.
等路由配置之前添加
您可以在 asp.net 核心中的 EndPoint 中使用回退,如下所示(在 app.UseEndpoints 内)和 razor 页面(NotFound 是页面文件夹中的 razor 页面而不是控制器)
endpoints.MapRazorPages();
endpoints.MapFallback( context => {
context.Response.Redirect("/NotFound");
return Task.CompletedTask;
});
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();
}
在处理 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
url 是我的自定义页面,您可以为您的应用程序设计。
我正在使用下面的中间件为 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 未找到错误页面。
有没有办法处理不匹配任何路由的请求?在 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>
基于 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 的问题。
我找到的最好的教程之一是: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
class,在 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...
.
您可以在 asp.net 核心中的 EndPoint 中使用回退,如下所示(在 app.UseEndpoints 内)和 razor 页面(NotFound 是页面文件夹中的 razor 页面而不是控制器)
endpoints.MapRazorPages();
endpoints.MapFallback( context => {
context.Response.Redirect("/NotFound");
return Task.CompletedTask;
});
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();
}
在处理 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
url 是我的自定义页面,您可以为您的应用程序设计。