Обработка ошибок в минимальных приложениях API
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 8 этой статьи.
В этой статье описывается обработка ошибок в минимальных приложениях API. Сведения об обработке ошибок в API на основе контроллера см. в разделе "Обработка ошибок в ASP.NET Core и обработка ошибок в веб-API на основе контроллера ASP.NET core".
Исключения
В приложении API "Минимальный" существует два встроенных централизованных механизма для обработки необработанных исключений:
- ПО промежуточного слоя страницы исключений разработчика (только для использования в среде разработки).)
- ПО промежуточного слоя обработчика исключений
В этом разделе приведен пример приложения, демонстрирующий способы обработки исключений в минимальном API. Он создает исключение при запросе конечной точки /exception
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
Страница со сведениями об исключении для разработчика
Страница исключений для разработчика содержит подробные сведения о необработанных исключениях запросов. Он использует DeveloperExceptionPageMiddleware для записи синхронных и асинхронных исключений из конвейера HTTP и для создания ответов об ошибках. Страница со сведениями об исключении для разработчика запускается в начале конвейера ПО промежуточного слоя, чтобы можно было перехватывать необработанные исключения, вызываемые в последующем ПО промежуточного слоя.
Приложения ASP.NET Core по умолчанию включают страницу со сведениями об исключении при выполнении всех следующих условий:
- Выполнение в среде разработки.
- Приложение было создано с использованием текущих шаблонов.WebApplication.CreateBuilder
Приложения, созданные с помощью WebHost.CreateDefaultBuilderпредыдущих шаблонов, могут включить страницу исключения разработчика, вызвав вызов app.UseDeveloperExceptionPage
.
Предупреждение
Не включите страницу исключений разработчика, если приложение не запущено в среде разработки. Не делитесь подробными сведениями об исключениях публично при запуске приложения в рабочей среде. Дополнительные сведения о настройке сред см. в статье Использование нескольких сред в ASP.NET Core.
Страница исключений для разработчика может содержать следующие сведения об исключении и запросе:
- Трассировка стека
- параметры строки запроса (при наличии);
- Файлы cookie, если таковые есть
- Заголовки
- Метаданные конечной точки, если таковые есть
Страница со сведениями об исключении для разработчика не гарантирует предоставление каких-либо сведений. Используйте Ведение журнала для получения полных сведений об ошибке.
На следующем рисунке показана пример страницы исключений разработчика с анимацией для отображения вкладок и отображаемых сведений:
В ответ на запрос с заголовком страница исключений разработчика возвращает обычный Accept: text/plain
текст вместо HTML. Например:
Status: 500 Internal Server Error
Time: 9.39 msSize: 480 bytes
FormattedRawHeadersRequest
Body
text/plain; charset=utf-8, 480 bytes
System.InvalidOperationException: Sample Exception
at WebApplicationMinimal.Program.<>c.<Main>b__0_0() in C:\Source\WebApplicationMinimal\Program.cs:line 12
at lambda_method1(Closure, Object, HttpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
HEADERS
=======
Accept: text/plain
Host: localhost:7267
traceparent: 00-0eab195ea19d07b90a46cd7d6bf2f
Чтобы просмотреть страницу исключений разработчика, выполните следующие действия.
- Запустите пример приложения в среде разработки.
- Перейдите к конечной точке
/exception
.
Обработчик исключений
В средах, отличных от разработки, используйте ПО промежуточного слоя обработчика исключений для создания полезных данных об ошибке. Чтобы настроить Exception Handler Middleware
, вызовите UseExceptionHandler.
Например, следующий код изменяет приложение для реагирования на полезные данные, совместимые с RFC 7807, на клиент. Дополнительные сведения см . в разделе "Сведения о проблеме" далее в этой статье.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp
=> exceptionHandlerApp.Run(async context
=> await Results.Problem()
.ExecuteAsync(context)));
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
Ответы на ошибки клиента и сервера
Рассмотрим следующее минимальное приложение API.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)));
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
/users
Конечная точка создает 200 OK
представление json
о том, User
когда id
больше 0
, в противном случае 400 BAD REQUEST
код состояния без текста ответа. Дополнительные сведения о создании ответа см. в статье "Создание ответов" в приложениях API "Минимальный".
Его Status Code Pages middleware
можно настроить для создания общего содержимого текста, если пусто для всех ответов HTTP-клиента (499
-400
) или сервера.500
-599
ПО промежуточного слоя настраивается путем вызова метода расширения UseStatusCodePages .
Например, в следующем примере приложение изменяет ответ на полезные данные, совместимые с RFC 7807, для всех ответов клиента и сервера, включая ошибки маршрутизации (например, 404 NOT FOUND
). Дополнительные сведения см. в разделе "Сведения о проблеме".
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.MapGet("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
Сведения о проблеме
Сведения о проблеме — это не единственный формат ответа, описывающий ошибку API HTTP, однако они часто используются для сообщения об ошибках для API HTTP.
Служба сведений о проблеме IProblemDetailsService реализует интерфейс, который поддерживает создание сведений о проблеме в ASP.NET Core. Метод AddProblemDetails(IServiceCollection) расширения для IServiceCollection регистрации реализации по умолчанию IProblemDetailsService
.
В приложениях ASP.NET Core следующий по промежуточному слоя создает ответы HTTP для получения сведений о проблемах при AddProblemDetails
вызове, за исключением случаев, когда Accept
заголовок HTTP запроса не включает один из типов контента, поддерживаемых зарегистрированным IProblemDetailsWriter (по умолчанию: application/json
):
- ExceptionHandlerMiddleware: создает ответ сведений о проблеме, когда настраиваемый обработчик не определен.
- StatusCodePagesMiddleware: создает ответ сведений о проблеме по умолчанию.
- DeveloperExceptionPageMiddleware: создает ответ сведений о проблеме в разработке, если
Accept
заголовок HTTP запроса не включаетtext/html
.
Минимальные приложения API можно настроить для создания ответа сведений о проблеме для всех ответов об ошибках HTTP-клиента и сервера, которые еще не содержат содержимого AddProblemDetails
текста с помощью метода расширения.
Следующий код настраивает приложение для создания сведений о проблеме:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
app.MapGet("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)));
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
Дополнительные сведения об использовании AddProblemDetails
см. в разделе "Сведения о проблеме"
Резервная часть IProblemDetailsService
В следующем коде возвращает ошибку, httpContext.Response.WriteAsync("Fallback: An error occurred.")
если IProblemDetailsService реализация не может создать ProblemDetails:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async httpContext =>
{
var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
if (pds == null
|| !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
{
// Fallback behavior
await httpContext.Response.WriteAsync("Fallback: An error occurred.");
}
});
});
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
Предыдущий код:
- Записывает сообщение об ошибке с резервным кодом, если не
problemDetailsService
удается написать сообщение об ошибкеProblemDetails
. Например, конечная точка, в которой заголовок запроса Accept указывает тип носителя, которыйDefaulProblemDetailsWriter
не поддерживается. - Использует ПО промежуточного слоя обработчика исключений.
Следующий пример аналогичен предыдущему, за исключением того, что вызывается .Status Code Pages middleware
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseStatusCodePages(statusCodeHandlerApp =>
{
statusCodeHandlerApp.Run(async httpContext =>
{
var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
if (pds == null
|| !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
{
// Fallback behavior
await httpContext.Response.WriteAsync("Fallback: An error occurred.");
}
});
});
app.MapGet("/users/{id:int}", (int id) =>
{
return id <= 0 ? Results.BadRequest() : Results.Ok(new User(id));
});
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
В этой статье описывается обработка ошибок в минимальных приложениях API.
Исключения
В приложении API "Минимальный" существует два встроенных централизованных механизма для обработки необработанных исключений:
- ПО промежуточного слоя страницы исключений разработчика (только для использования в среде разработки).)
- ПО промежуточного слоя обработчика исключений
В этом разделе описывается следующее приложение API с минимальным количеством способов обработки исключений. Он создает исключение при запросе конечной точки /exception
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Страница со сведениями об исключении для разработчика
На странице исключений разработчика отображаются подробные трассировки стека для ошибок сервера. Он использует DeveloperExceptionPageMiddleware для записи синхронных и асинхронных исключений из конвейера HTTP и для создания ответов об ошибках.
Приложения ASP.NET Core по умолчанию включают страницу со сведениями об исключении при выполнении всех следующих условий:
- Выполнение в среде разработки.
- Приложение использует WebApplication.CreateBuilder.
Дополнительные сведения о настройке ПО промежуточного слоя см. в разделе "По промежуточного слоя" в минимальных приложениях API.
Developer Exception Page
При обнаружении необработанного исключения при обнаружении необработанного исключения создается ответ обычного текста по умолчанию, аналогичный следующему примеру:
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
Date: Thu, 27 Oct 2022 18:00:59 GMT
Server: Kestrel
Transfer-Encoding: chunked
System.InvalidOperationException: Sample Exception
at Program.<>c.<<Main>$>b__0_1() in ....:line 17
at lambda_method2(Closure, Object, HttpContext)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Connection: keep-alive
Host: localhost:5239
Accept-Encoding: gzip, deflate, br
Предупреждение
Не включите страницу исключений разработчика, если приложение не запущено в среде разработки. Не делитесь подробными сведениями об исключениях публично при запуске приложения в рабочей среде. Дополнительные сведения о настройке сред см. в статье Использование нескольких сред в ASP.NET Core.
Обработчик исключений
В средах, отличных от разработки, используйте ПО промежуточного слоя обработчика исключений для создания полезных данных об ошибке. Чтобы настроить Exception Handler Middleware
, вызовите UseExceptionHandler.
Например, следующий код изменяет приложение для реагирования на полезные данные, совместимые с RFC 7807, на клиент. Дополнительные сведения см. в разделе "Сведения о проблеме".
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp
=> exceptionHandlerApp.Run(async context
=> await Results.Problem()
.ExecuteAsync(context)));
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Ответы на ошибки клиента и сервера
Рассмотрим следующее минимальное приложение API.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Run();
public record User(int Id);
/users
Конечная точка создает 200 OK
представление json
о том, User
когда id
больше 0
, в противном случае 400 BAD REQUEST
код состояния без текста ответа. Дополнительные сведения о создании ответа см. в статье "Создание ответов" в приложениях API "Минимальный".
Его Status Code Pages middleware
можно настроить для создания общего содержимого текста, если пусто для всех ответов HTTP-клиента (499
-400
) или сервера.500
-599
ПО промежуточного слоя настраивается путем вызова метода расширения UseStatusCodePages .
Например, в следующем примере приложение изменяет ответ на полезные данные, совместимые с RFC 7807, для всех ответов клиента и сервера, включая ошибки маршрутизации (например, 404 NOT FOUND
). Дополнительные сведения см. в разделе "Сведения о проблеме".
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("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Run();
public record User(int Id);
Сведения о проблеме
Сведения о проблеме — это не единственный формат ответа, описывающий ошибку API HTTP, однако они часто используются для сообщения об ошибках для API HTTP.
Служба сведений о проблеме IProblemDetailsService реализует интерфейс, который поддерживает создание сведений о проблеме в ASP.NET Core. Метод AddProblemDetails(IServiceCollection) расширения для IServiceCollection регистрации реализации по умолчанию IProblemDetailsService
.
В приложениях ASP.NET Core следующий по промежуточному слоя создает ответы HTTP для получения сведений о проблемах при AddProblemDetails
вызове, за исключением случаев, когда Accept
заголовок HTTP запроса не включает один из типов контента, поддерживаемых зарегистрированным IProblemDetailsWriter (по умолчанию: application/json
):
- ExceptionHandlerMiddleware: создает ответ сведений о проблеме, когда настраиваемый обработчик не определен.
- StatusCodePagesMiddleware: создает ответ сведений о проблеме по умолчанию.
- DeveloperExceptionPageMiddleware: создает ответ сведений о проблеме в разработке, если
Accept
заголовок HTTP запроса не включаетtext/html
.
Минимальные приложения API можно настроить для создания ответа сведений о проблеме для всех ответов на ошибки HTTP-клиента и сервера, которые еще не содержат содержимое текста с помощью AddProblemDetails
метода расширения.
Следующий код настраивает приложение для создания сведений о проблеме:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
app.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Дополнительные сведения об использовании AddProblemDetails
см. в разделе "Сведения о проблеме"
ASP.NET Core