ASP.NET MVC 6 обработка ошибок на основе кода состояния HTTP
Я хочу отображать различные сообщения об ошибках для каждого кода состояния e.g:
- 400 Плохой Запрос
- 403-запрещено
- 500 Внутренняя Ошибка Сервера
- 404 Не Найдена
- 401 несанкционированный
Как я могу достичь этого в новом ASP.NET MVC 6 приложений? Могу ли я сделать это с помощью встроенного метода UseErrorHandler?
application.UseErrorHandler("/error");
кроме того, я заметил, что даже с выше обработчика ввода несуществующий URL, например /this-page-does-not-exist, вызывает уродливую 404 не найденную страницу ошибки из IIS. Как можно справиться и с этим?
в MVC 5 нам пришлось использовать систему.раздел Web customerrors для ASP.NET и система.раздел httpErrors веб-сервера в интернете.файл конфигурации, но было трудно работать с громоздким, с большим количеством очень странного поведения. Делает ли MVC 6 это намного проще?
3 ответов
можно использовать StatusCodePagesMiddleware
для этого. Ниже приведен пример:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseStatusCodePagesWithReExecute("/StatusCodes/StatusCode{0}");
app.UseMvcWithDefaultRoute();
контроллер, который обрабатывает запросы статуса код:
public class StatusCodesController : Controller
{
public IActionResult StatusCode404()
{
return View(viewName: "NotFound"); // you have a view called NotFound.cshtml
}
... more actions here to handle other status codes
}
Некоторые Замечания:
- проверьте другие методы расширения, такие как
UseStatusCodePagesWithRedirects
иUseStatusCodePages
для других возможностей. - я попытался иметь StatusCode в качестве строки запроса в моем примере, но выглядит так промежуточное ПО не обрабатывает строки запросов, но вы можете взглянуть на этой код и исправить эту проблему.
как я могу достичь этого в новом ASP.NET MVC 6 приложений? Могу ли я сделать это с помощью встроенного метода UseErrorHandler?
короткий ответ: не в элегантной манере.
Объяснение/Альтернатива: для начала давайте сначала посмотрим, что UseErrorHandler
метод фактически делает: https://github.com/aspnet/Diagnostics/blob/6dbbe831c493e6e7259de81f83a04d1654170137/src/Microsoft.AspNet.Diagnostics/ErrorHandlerExtensions.cs#L25 который добавляет следующее промежуточное ПО: https://github.com/aspnet/Diagnostics/blob/6dbbe831c493e6e7259de81f83a04d1654170137/src/Microsoft.AspNet.Diagnostics/ErrorHandlerMiddleware.cs Примечание строки 29-78 (метод invoke)
метод invoke выполняется всякий раз, когда приходит запрос (контролируется местоположением вашего application.UseErrorHandler("...")
в своем Startup.cs
). Так что UseErrorHandler
- это прославленный способ добавления пользовательского промежуточного ПО: middleware = компонент, который может действовать по http-запросу.
теперь с этим фоном, если мы хотим добавить наше собственное промежуточное ПО ошибок, которое дифференцировало запросы. Мы могли бы сделать это, добавив аналогичное промежуточное ПО, которое похоже на default ErrorHandlerMiddleware
изменяя эти линии: https://github.com/aspnet/Diagnostics/blob/6dbbe831c493e6e7259de81f83a04d1654170137/src/Microsoft.AspNet.Diagnostics/ErrorHandlerMiddleware.cs#L48-L51 при таком подходе мы могли бы контролировать путь перенаправления на основе кода состояния.
в MVC 5 нам пришлось использовать систему.раздел Web customerrors для ASP.NET и система.раздел httpErrors веб-сервера в интернете.конфигурационный файл, но было сложно работать с громоздким, с большим количеством Очень странных поведение. Делает ли MVC 6 это намного проще?
ответ: это точно :). Как и в приведенном выше ответе, исправление заключается в добавлении промежуточного ПО. Существует ярлык для добавления простого промежуточного ПО через IApplicationBuilder
в своем Startup.cs
; в конце Configure
метод вы можете добавить следующее:
app.Run(async (context) =>
{
await context.Response.WriteAsync("Could not handle the request.");
// Nothing else will run after this middleware.
});
это будет работать, потому что это означает, что вы достигли конца вашего http-конвейера без обработки запроса (так как он находится в конце вашего Configure
метод Startup.cs
). Если вы хотите добавить это промежуточное по (быстрым способом) с возможностью выполнения промежуточного ПО после вас, вот как:
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Could not handle the request.");
// This ensures that any other middelware added after you runs.
await next();
});
надеюсь, что это помогает!
работает с различными кодами состояния без указания каждого отдельно в контроллере.
Автозагрузка.cs:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseStatusCodePagesWithRedirects("/StatusCodes?statusCode={0}");
app.UseMvcWithDefaultRoute();
:
public class StatusCodesController : Controller
{
public IActionResult Index(string statusCode)
{
if(statusCode == null) statusCode = "";
if(statusCode == "404") return View("Error404");
return View("Index",statusCode);
}
public IActionResult Test404() { return StatusCode(404); }
public IActionResult Test500() { return StatusCode(500); }
вид:
@model string
@{ ViewData["Title"] = Model + " Oops!"; }
<style>
.error-template {
padding: 40px 15px;
text-align: center;
}
.error-actions {
margin-bottom: 15px;
margin-top: 15px;
}
.error-actions .btn {
margin-right: 10px;
}
</style>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="error-template">
<h2>Oops!</h2>
<h2>@Model Error</h2>
<div class="error-details">Sorry, an error has occurred!</div>
<div class="error-actions">
<a class="btn btn-primary btn-lg" href="/"><span class="glyphicon glyphicon-home"></span> Take Me Home </a>
<a class="btn btn-default btn-lg" href="/Home/ContactUs"><span class="glyphicon glyphicon-envelope"></span> Contact Support </a>
</div>
</div>
</div>
</div>
</div>