Подумайте об упрощении вашего контроллера, перенеся логику обработки ошибок в выделенный класс промежуточного программного обеспечения.
Представьте себе простой контроллер, подобный этому, все, что он делает, это определяет целевые страницы для маршрутизации и включает пример исключения для имитации ошибки 500. Это не заботится о конкретных типах ошибок. (Anon доступ разрешен для простоты.)
Проект называется TestError .
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace TestError.Controllers
{
[AllowAnonymous]
public class HomeController : Controller
{
public HomeController() { }
[HttpGet]
public ViewResult Home() => View("Home");
[HttpGet]
public ViewResult Bogus() => throw new Exception("Bogus error");
[HttpGet]
public ViewResult Error() => View("Error");
[HttpGet]
public ViewResult PageNotFound() => View("PageNotFound");
}
}
In Startup.cs , чуть вышеВ определениях маршрутов есть ссылка на обработчик ошибок: app.UseMiddleware<ErrorHandler>();
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TestError.Infrastructure;
namespace TestError
{
public class Startup
{
// Updated this class for ASP.NET Core 3
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStatusCodePages();
app.UseStaticFiles();
app.UseMiddleware<ErrorHandler>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "Default",
pattern: "{controller=Home}/{action=Home}/{id?}");
endpoints.MapControllerRoute(name: "Error",
"error",
new { controller = "Home", action = "Error" });
endpoints.MapControllerRoute(name: "PageNotFound",
"pagenotfound",
new { controller = "Home", action = "PageNotFound" });
});
}
}
}
Startup.cs также требуется ссылка как using TestError.Infrastructure;
, поскольку класс промежуточного программного обеспечения создается как Infrastructure \ ErrorHandler.cs
Класс промежуточного программного обеспечения просматривает конвейер HttpContext context.Response.StatusCode
и использует оператор switch, вызывая пользовательский метод для ответа на каждую ошибку по мере необходимости, и я добавил предложениеза ошибку 404.
Вы можете добавлять дополнительные предложения для различных кодов ошибок по мере необходимости и добавлять пользовательские методы для работы с конкретными обстоятельствами или создавать их в отдельных классах, если вы хотите, чтобы обработчик ошибок не становился слишком сложным испецифичные.
Общие исключения кода обрабатываются отдельно как 500 ошибок, перехваченных блоком catch.
using System;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace TestError.Infrastructure
{
public class ErrorHandler
{
private readonly RequestDelegate _next;
public ErrorHandler(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
// Handle specific HTTP status codes
switch (context.Response.StatusCode)
{
case 404:
HandlePageNotFound(context);
break;
case 418:
// Not implemented
break;
default:
break;
}
}
catch (Exception e)
{
// Handle uncaught global exceptions (treat as 500 error)
HandleException(context, e);
}
finally
{
}
}
// 500
private static void HandleException(HttpContext context, Exception e)
{
context.Response.Redirect("/Error");
}
// 404
private static void HandlePageNotFound(HttpContext context)
{
// Display an information page that displays the bad url using a cookie
string pageNotFound = context.Request.Path.ToString().TrimStart('/');
CookieOptions cookieOptions = new CookieOptions();
cookieOptions.Expires = DateTime.Now.AddMilliseconds(10000);
cookieOptions.IsEssential = true;
context.Response.Cookies.Append("PageNotFound", pageNotFound, cookieOptions);
context.Response.Redirect("/PageNotFound");
}
}
}
Метод HandleException создает перенаправление на "/ Ошибка"page.
Error.cshtml в значительной степени соответствует ожиданиям
@{
Layout = "~/Views/Shared/_Layout_Main.cshtml";
ViewData["Title"] = "Error";
}
<div id="dataSection">
<div class="TextLine Label">An error occurred while processing your request</div>
</div>
HandlePageNotFound создает недолговечный файл cookie для храненияадрес запрашиваемой страницы и перенаправляет на "/PageNotFound".
PageNotFound.cshtml ссылается на cookie для отображения значимой ошибки
@{
Layout = "_Layout_Main";
ViewData["Title"] = "Page Not Found";
string notFoundMessage = "Sorry, The page cannot be found";
string pageNotFound = Context.Request.Cookies["PageNotFound"];
if (pageNotFound != null){
notFoundMessage += " : ";
}
}
<div id="dataSection">
<div class="TextLine Label">@notFoundMessage<b>@pageNotFound</b></div>
</div>
Пример использования, тамдомашняя страница выглядит следующим образом (со страницей макета)
@{
ViewData["Title"] = "Home";
Layout = "~/Views/Shared/_Layout_Main.cshtml";
}
<h1>Hello World</h1>
Пример 1, / Home / Home : находки Home.cshtml Пример 2, / Nopage : перенаправляет на PageNotFound.cshtml Пример 3, / Home / Bogus : создает исключение и перенаправляет на Ошибка.cshtml
Надеюсь, это поможет при обработке ошибок. Существует множество вариантов этого, и, как уже упоминалось, вы можете добавить больше предложений switch и даже включить конкретный регистр для 500.
Более подробный пример также будет включать в себя некоторые записи, которые я исключил для простоты. .