В преддверии старта курса C# ASP.NET Core разработчик подготовили традиционный перевод полезного материала.
Также рекомендуем посмотреть вебинар на тему Отличия структурных шаблонов проектирования на примерах. На этом открытом уроке участники вместе с преподавателем-экспертом познакомятся с тремя структурными шаблонами проектирования: Заместитель, Адаптер и Декоратор.
Введение
Сегодня в этой статье мы обсудим концепцию обработки исключений в приложениях ASP.NET Core. Обработка исключений (exception handling) одна из наиболее важных импортируемых функций или частей любого типа приложений, которой всегда следует уделять внимание и правильно реализовывать. Исключения это в основном средства ориентированные на обработку рантайм ошибок, которые возникают во время выполнения приложения. Если этот тип ошибок не обрабатывать должным образом, то приложение будет остановлено в результате их появления.
В ASP.NET Core концепция обработки исключений подверглась некоторым изменениям, и теперь она, если можно так сказать, находится в гораздо лучшей форме для внедрения обработки исключений. Для любых API-проектов реализация обработки исключений для каждого действия будет отнимать довольно много времени и дополнительных усилий. Но мы можем реализовать глобальный обработчик исключений (Global Exception handler), который будет перехватывать все типы необработанных исключений. Преимущество реализации глобального обработчика исключений состоит в том, что нам нужно определить его всего лишь в одном месте. Через этот обработчик будет обрабатываться любое исключение, возникающее в нашем приложении, даже если мы объявляем новые методы или контроллеры. Итак, в этой статье мы обсудим, как реализовать глобальную обработку исключений в ASP.NET Core Web API.
Создание проекта ASP.NET Core Web API в Visual Studio 2019
Итак, прежде чем переходить к обсуждению глобального обработчика исключений, сначала нам нужно создать проект ASP.NET Web API. Для этого выполните шаги, указанные ниже.
-
Откройте Microsoft Visual Studio и нажмите Create a New Project (Создать новый проект).
-
В диалоговом окне Create New Project выберите ASP.NET Core Web Application for C# (Веб-приложение ASP.NET Core на C#) и нажмите кнопку Next (Далее).
-
В окне Configure your new project (Настроить новый проект) укажите имя проекта и нажмите кнопку Create (Создать).
-
В диалоговом окне Create a New ASP.NET Core Web Application (Создание нового веб-приложения ASP.NET Core) выберите API и нажмите кнопку Create.
-
Убедитесь, что флажки Enable Docker Support (Включить поддержку Docker) и Configure for HTTPS (Настроить под HTTPS) сняты. Мы не будем использовать эти функции.
-
Убедитесь, что выбрано No Authentication (Без аутентификации), поскольку мы также не будем использовать аутентификацию.
-
Нажмите ОК.
Используем UseExceptionHandler middleware в ASP.NET Core.
Чтобы реализовать глобальный обработчик исключений, мы можем воспользоваться преимуществами встроенного Middleware ASP.NET Core. Middleware представляет из себя программный компонент, внедренный в конвейер обработки запросов, который каким-либо образом обрабатывает запросы и ответы. Мы можем использовать встроенное middleware ASP.NET Core UseExceptionHandler в качестве глобального обработчика исключений. Конвейер обработки запросов ASP.NET Core включает в себя цепочку middleware-компонентов. Эти компоненты, в свою очередь, содержат серию делегатов запросов, которые вызываются один за другим. В то время как входящие запросы проходят через каждый из middleware-компонентов в конвейере, каждый из этих компонентов может либо обработать запрос, либо передать запрос следующему компоненту в конвейере.
С помощью этого middleware мы можем получить всю
детализированную информацию об объекте исключения, такую как
стектрейс, вложенное исключение, сообщение и т. д., а также вернуть
эту информацию через API в качестве вывода. Нам нужно поместить
middleware обработки исключений в configure()
файла
startup.cs
. Если мы используем какое-либо приложение
на основе MVC, мы можем использовать middleware обработки
исключений, как это показано ниже. Этот фрагмент кода
демонстрирует, как мы можем настроить middleware
UseExceptionHandler
для перенаправления пользователя
на страницу с ошибкой при возникновении любого типа исключения.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseExceptionHandler("/Home/Error"); app.UseMvc(); }
Теперь нам нужно проверить сообщение об исключении. Для этого
откройте файл WeatherForecastController.cs
и добавьте
следующий экшн-метод, чтобы пробросить исключение:
[Route("GetExceptionInfo")] [HttpGet] public IEnumerable<string> GetExceptionInfo() { string[] arrRetValues = null; if (arrRetValues.Length > 0) { } return arrRetValues; }
Если мы хотим получить подробную информацию об объектах исключения, например, стектрейс, сообщение и т. д., мы можем использовать приведенный ниже код в качестве middleware исключения
app.UseExceptionHandler( options => { options.Run( async context => { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.ContentType = "text/html"; var exceptionObject = context.Features.Get<IExceptionHandlerFeature>(); if (null != exceptionObject) { var errorMessage = $"<b>Exception Error: {exceptionObject.Error.Message} </b> {exceptionObject.Error.StackTrace}"; await context.Response.WriteAsync(errorMessage).ConfigureAwait(false); } }); } );
Для проверки вывода просто запустите эндпоинт API в любом браузере:
Определение пользовательского Middleware для обработки исключений в API ASP.NET Core
Кроме того, мы можем написать собственное
middleware
для обработки любых типов исключений. В
этом разделе мы продемонстрируем, как создать типичный
пользовательский класс middleware
. Пользовательское
middleware
также обеспечивает гораздо большую гибкость
для обработки исключений. Мы можем добавить стекатрейс, имя типа
исключения, код ошибки или что-нибудь еще, что мы захотим включить
как часть сообщения об ошибке. В приведенном ниже фрагменте кода
показан типичный пользовательский класс
middleware
:
using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; namespace API.DemoSample.Exceptions { public class ExceptionHandlerMiddleware { private readonly RequestDelegate _next; public ExceptionHandlerMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { try { await _next.Invoke(context); } catch (Exception ex) { } } } }
В приведенном выше классе делегат запроса передается любому
middleware
. Middleware
либо обрабатывает
его, либо передает его следующему middleware
в
цепочке. Если запрос не успешен, будет выброшено исключение, а
затем будет выполнен метод HandleExceptionMessageAsync
в блоке catch
. Итак, давайте обновим код метода
Invoke
, как показано ниже:
public async Task Invoke(HttpContext context) { try { await _next.Invoke(context); } catch (Exception ex) { await HandleExceptionMessageAsync(context, ex).ConfigureAwait(false); } }
Теперь нам нужно реализовать метод
HandleExceptionMessageAsync
, как показано ниже:
private static Task HandleExceptionMessageAsync(HttpContext context, Exception exception) { context.Response.ContentType = "application/json"; int statusCode = (int)HttpStatusCode.InternalServerError; var result = JsonConvert.SerializeObject(new { StatusCode = statusCode, ErrorMessage = exception.Message }); context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; return context.Response.WriteAsync(result); }
Теперь, на следующем шаге, нам нужно создать статический класс с
именем ExceptionHandlerMiddlewareExtensions
и добавить
приведенный ниже код в этот класс,
using Microsoft.AspNetCore.Builder; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace API.DemoSample.Exceptions { public static class ExceptionHandlerMiddlewareExtensions { public static void UseExceptionHandlerMiddleware(this IApplicationBuilder app) { app.UseMiddleware<ExceptionHandlerMiddleware>(); } } }
На последнем этапе, нам нужно включить наше пользовательское middleware в методе Configure класса startup, как показано ниже:
app.UseExceptionHandlerMiddleware();
Заключение
Обработка исключений это по сути сквозная функциональность для любого типа приложений. В этой статье мы обсудили процесс реализации концепции глобальной обработки исключений. Мы можем воспользоваться преимуществами глобальной обработки исключений в любом приложении ASP.NET Core, чтобы гарантировать, что каждое исключение будет перехвачено и вернет правильные сведения, связанные с этим исключением. С глобальной обработкой исключений нам достаточно в одном месте написать код, связанный с обработкой исключений, для всего нашего приложения. Любые предложения, отзывы или запросы, связанные с этой статьей, приветствуются.
Узнать подробнее о курсе C# ASP.NET Core разработчик.
Посмотреть вебинар на тему Отличия структурных шаблонов проектирования на примерах.