可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Instead of getting a HTTP 404 response, I'd like to have a generic 404 Not Found page (HTTP 200). I know you can set that up in MVC 5 with
<customErrors mode="On">
<error statusCode="404" redirect="~/Error/NotFound" />
</customErrors>
But I can't seem to figure out how to do this in MVC 6. I'm guessing it should be in either the UseMvc routing table, or a custom middleware.
回答1:
Startup.cs:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
// PICK YOUR FLAVOR.
// app.UseErrorPage(ErrorPageOptions.ShowAll);
app.UseStatusCodePages(); // There is a default response but any of the following can be used to change the behavior.
// app.UseStatusCodePages(context => context.HttpContext.Response.SendAsync("Handler, status code: " + context.HttpContext.Response.StatusCode, "text/plain"));
// app.UseStatusCodePages("text/plain", "Response, status code: {0}");
// app.UseStatusCodePagesWithRedirects("~/errors/{0}"); // PathBase relative
// app.UseStatusCodePagesWithRedirects("/base/errors/{0}"); // Absolute
// app.UseStatusCodePages(builder => builder.UseWelcomePage());
// app.UseStatusCodePagesWithReExecute("/errors/{0}");
}
}
project.json:
"dependencies": {
"Microsoft.AspNet.Diagnostics": "1.0.0-*",
// ....
}
note that, if you are hosting on IIS (or azure), the web.config
does still works and it's big maybe needed in some hosting scenarios. (it should be placed inside wwwroot
folder
回答2:
You can handle 404 errors with the UseStatusCodePagesWithReExecute
but you need to set the status code at the end of your configure pipeline first.
public void Configure(IApplicationBuilder app)
{
app.UseIISPlatformHandler();
if (string.Equals(_env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
app.UseDeveloperExceptionPage();
app.UseRuntimeInfoPage();
} else
{
app.UseExceptionHandler("/Error");
}
app.UseStatusCodePagesWithReExecute("/Error/Status/{0}");
app.UseStaticFiles();
app.UseMvc();
app.Use((context, next) =>
{
context.Response.StatusCode = 404;
return next();
});
}
This will set the status code to 404 if nothing in the pipeline can handle it (which is what you want).
Then you can easily capture and handle the response any way you want in your controller.
[Route("error")]
public class ErrorController : Controller
{
[Route("Status/{statusCode}")]
public IActionResult StatusCode(int statusCode)
{
//logic to generate status code response
return View("Status", model);
}
}
回答3:
If anyone is looking to create custom 404 pages with HTML, you can do this:
Startup.cs
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseStatusCodePagesWithReExecute("/errors/{0}");
}
}
project.json
"dependencies": {
"Microsoft.AspNet.Diagnostics": "1.0.0-*",
// ....
}
ErrorsController.cs
public class ErrorsController : Controller
{
// ....
[Route("/Error/{statusCode}")]
public IActionResult ErrorRoute(string statusCode)
{
if (statusCode == "500" | statusCode == "404")
{
return View(statusCode);
}
return View("~/Views/Errors/Default.cshtml");
}
}
All that's left after this is to create a 404.cshtml, 500.cshtml, and Default.cshtml in your Errors view folder and customize the HTML to your liking.
回答4:
In the Configure function of the Startup class, call:
app.UseErrorPage(ErrorPageOptions.ShowAll);
more production ready:
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
app.UseBrowserLink();
app.UseErrorPage(ErrorPageOptions.ShowAll);
app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
}
else
{
// Add Error handling middleware which catches all application specific errors and
// send the request to the following path or controller action.
app.UseErrorHandler("/Home/Error");
}
回答5:
There is a middleware called StatusCodePagesMiddleware
which I believe was added post-Beta3.
Sample: https://github.com/aspnet/Diagnostics/blob/dev/samples/StatusCodePagesSample/Startup.cs
回答6:
If you have a standard ASP.NET 5 Web application template project you can get a really nice solution that will handle both keeping the error status code at the same time as you serve the cshtml file of your choice.
Startup.cs
, in the Configure
method
Replace
app.UseExceptionHandler("/Error");
with
app.UseStatusCodePagesWithReExecute("/Home/Errors/{0}");
Then remove the following catchall:
app.Run(async (context) =>
{
var logger = loggerFactory.CreateLogger("Catchall Endpoint");
logger.LogInformation("No endpoint found for request {path}", context.Request.Path);
await context.Response.WriteAsync("No endpoint found - try /api/todo.");
});
In HomeController.cs
Replace the current Error
method with the following one:
public IActionResult Errors(string id)
{
if (id == "500" | id == "404")
{
return View($"~/Views/Home/Error/{id}.cshtml");
}
return View("~/Views/Shared/Error.cshtml");
}
That way you can add error files you feel the users can benefit from (while search engines and such still get the right status codes)
Now add a folder named Error
in ~Views/Home
folder
Create two .cshtml
files. Name the first one 404.cshtml
and the second one 500.cshtml
.
Give them some useful content and the start the application and write something like http://localhost:44306/idonthaveanendpointhere
and confirm the setup works.
Also press F12 developer tools and confirm the status code is 404.