В ASP.NET Core 7 минимальные API-интерфейсы обеспечивают упрощенный способ создания веб-API с меньшим количеством стандартного кода. Тем не менее, ошибки все равно могут возникать, и вы должны быть в состоянии элегантно с ними справиться.
В этой статье обсуждается, как мы можем изящно обрабатывать ошибки в минимальных приложениях API в ASP.NET Core 7. Чтобы использовать примеры кода, представленные в этой статье, в вашей системе должна быть установлена Visual Studio 2022. Если у вас еще нет копии, вы можете скачать Visual Studio 2022 здесь.
Создайте минимальный проект веб-API ASP.NET Core 7 в Visual Studio 2022.
Прежде всего, давайте создадим проект ASP.NET Core 7 в Visual Studio 2022. Выполните следующие действия:
- Запустите интегрированную среду разработки Visual Studio 2022.
- Нажмите «Создать новый проект».
- В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
- Нажмите “Далее.
- В окне «Настроить новый проект» укажите имя и расположение нового проекта.
- При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
- Нажмите “Далее.
- В следующем окне «Дополнительная информация» выберите «NET 7.0 (Current)» в качестве платформы и снимите флажок «Использовать контроллеры…». Оставьте «Тип аутентификации» на «Нет» (по умолчанию).
- Убедитесь, что флажки «Включить поддержку OpenAPI», «Включить Docker», «Настроить для HTTPS» и «Включить поддержку Open API» не отмечены, так как мы не будем использовать эти функции здесь.
- Щелкните Создать.
Мы будем использовать этот проект веб-API ASP.NET Core 7 для создания минимального API и реализации обработки ошибок в следующих разделах.
Обработка ошибок в минимальных приложениях API
Замените сгенерированный по умолчанию исходный код файла Program.cs в созданном нами проекте следующим фрагментом кода.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("https://www.infoworld.com/", () => "Hello World!"); app.Map("/error", () => { throw new InvalidOperationException("An Error Occurred..."); }); app.Run();
Когда вы запускаете приложение, в вашем веб-браузере будет отображаться текстовое сообщение «Hello World». Если вы перейдете к конечной точке /error, произойдет ошибка времени выполнения, и выполнение приложения будет остановлено, как показано на рисунке 1.
Рис. 1. Фатальное исключение в нашем минимальном приложении API.
Существует два встроенных механизма обработки ошибок в минимальных приложениях API: ПО промежуточного слоя Developer Exception Page и промежуточное ПО обработчика исключений. Давайте рассмотрим каждый по очереди.
Использование ПО промежуточного слоя Developer Exception Page
Чтобы помочь разработчикам диагностировать и исправлять ошибки во время разработки, вы можете использовать ПО промежуточного слоя Developer Exception Page. Программное обеспечение промежуточного слоя Developer Exception Page отображает подробную информацию об ошибке в браузере при возникновении исключения.
Вот пример использования ПО промежуточного слоя Developer Exception Page в минимальном API.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.MapGet("https://www.infoworld.com/", () => "Hello, world!"); app.Run();
В этом примере метод UseDeveloperExceptionPage используется для добавления промежуточного программного обеспечения в конвейер. Промежуточное ПО включается только тогда, когда приложение работает в среде разработки, которая определяется методом app.Environment.IsDevelopment().
Если в конвейере возникает исключение, ПО промежуточного слоя Developer Exception Page перехватывает его и отображает подробную страницу ошибки в браузере. Страница ошибки содержит информацию об исключении, включая трассировку стека, сведения о запросе и переменные среды, как показано на рис. 2.
Рис. 2. Промежуточное ПО страницы исключений разработчика в действии.
Используя ПО промежуточного слоя Developer Exception Page, разработчики могут быстро диагностировать и исправлять ошибки во время разработки.
Использование промежуточного программного обеспечения обработчика исключений
ПО промежуточного слоя обработчика исключений перехватывает необработанные исключения и возвращает ответ об ошибке. Как правило, это ПО промежуточного слоя следует использовать в среде, не предназначенной для разработки. Вот пример использования ПО промежуточного слоя обработчика исключений в минимальном API.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseExceptionHandler(exceptionHandlerApp => exceptionHandlerApp.Run(async context => await Results.Problem().ExecuteAsync(context))); app.Map("/error", () => { throw new InvalidOperationException("An Error Occurred..."); }); app.MapGet("https://www.infoworld.com/", () => "Hello, world!"); app.Run();
В этом примере метод UseExceptionHandler используется для настройки этого промежуточного программного обеспечения. Параметр «/error» указывает конечную точку, на которую промежуточное ПО будет перенаправляться в случае возникновения исключения.
Если в конвейере возникает необработанное исключение, ПО промежуточного слоя обработки исключений перехватывает его и перенаправляет запрос в указанную конечную точку. Впоследствии ошибка будет обработана, и будет возвращено соответствующее сообщение об ошибке.
Используя ПО промежуточного слоя для обработки исключений, вы можете легко обрабатывать исключения, возникающие в минимальных API-интерфейсах в ASP.NET Core 7. Это может помочь повысить надежность и удобство использования вашего API.
Использование ProblemDetails для форматирования ответа
Класс ProblemDetails — это способ включить подробные сведения об ошибках, чтобы избежать создания настраиваемых форматов ответов об ошибках в ASP.NET Core. Метод расширения AddProblemDetails, относящийся к интерфейсу IServiceCollection, можно использовать для регистрации реализации IPProblemDetailsService по умолчанию.
Следующее ПО промежуточного слоя в ASP.NET Core создает HTTP-ответы ProblemDetails при вызове метода AddProblemDetailsMiddleware в приложении.
- ExceptionHandlerMiddleware: это промежуточное ПО используется для создания ответа ProblemDetails, если пользовательский обработчик недоступен.
- DeveloperExceptionPageMiddleware: DeveloperExceptionPageMiddleware создает ответ ProblemDetails, если HTTP-заголовок Accept не содержит text/html.
- StatusCodePagesMiddleware: по умолчанию StatusCodePagesMiddleware создает ответы ProblemDetails.
В следующем листинге кода показано, как можно использовать ProblemDetails в минимальных API.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddProblemDetails(); var app = builder.Build(); app.UseExceptionHandler(); app.UseStatusCodePages(); app.Map("/authors/{id:int}", (int id) => id <= 0 ? Results.BadRequest() : Results.Ok(new Author(id))); app.Map("/error", () => { throw new InvalidOperationException("An Error Occurred..."); }); app.Run(); public record Author(int Id);
В этом примере конечная точка /error извлекает информацию об исключении из HttpContext и создает объект ProblemDetails со сведениями об ошибке. Затем он устанавливает код состояния ответа и тип содержимого и возвращает объект ProblemDetails в виде ответа JSON.
Использование промежуточного программного обеспечения кодовых страниц состояния для создания тела ответа
Когда приложение ASP.NET Core обнаруживает коды ошибок HTTP, такие как «404 — Not Found», оно по умолчанию не предоставляет кодовую страницу состояния. Всякий раз, когда текст ответа не предоставляется для кода состояния ошибки HTTP 400-599, приложение возвращает код состояния и пустой текст ответа.
Вы можете вызвать метод UseStatusCodePages в файле Program.cs вашего приложения, чтобы включить текстовые обработчики для распространенных кодов состояния ошибок. Вы можете использовать класс StatusCodePagesMiddleware в ASP.NET Core для создания ответа, как показано во фрагменте кода, приведенном ниже.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseStatusCodePages(async statusCodeContext => await Results.Problem(statusCode: statusCodeContext.HttpContext.Response.StatusCode) .ExecuteAsync(statusCodeContext.HttpContext)); app.Map("/authors/{id:int}", (int id) => id <= 0 ? Results.BadRequest() : Results.Ok(new Author(id))); app.Run(); public record Author(int Id);
В приложениях ASP.NET Core фильтры исключений можно использовать для перехвата определенных типов исключений и корректной их обработки. Чтобы использовать фильтр, реализуйте интерфейс IExceptionFilter и добавьте его в конвейер приложения. Вы можете узнать больше об использовании фильтров исключений (и других фильтров) в ASP.NET Core в моей предыдущей статье здесь.