注
これは、この記事の最新バージョンではありません。 現在のリリースについては、 この記事の .NET 10 バージョンを参照してください。
Warnung
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
この記事では、ASP.NET Core API のエラーを処理する方法について説明します。 最小限の API のドキュメントが選択されています。 コントローラー ベースの API のドキュメントを表示するには、[ コントローラー ] タブを選択します。エラー処理ガイダンス Blazor については、「 ASP.NET Core Blazor アプリでのエラーの処理」を参照してください。
開発者例外ページ
[開発者例外] ページには、未処理の要求例外に関する詳細情報が表示されます。 DeveloperExceptionPageMiddlewareを使用して、HTTP パイプラインから同期例外と非同期例外をキャプチャし、エラー応答を生成します。 開発者例外ページはミドルウェア パイプラインの早い段階で実行されるため、次のミドルウェアでスローされたハンドルされない例外をキャッチできます。
ASP.NET Core アプリでは、次の両方の場合に開発者例外ページが既定で有効になります。
- 開発環境で実行されています。
- アプリは、現在のテンプレート (つまり、 WebApplication.CreateBuilderを使用して) で作成されました。
以前のテンプレートを使用して作成されたアプリ(つまり、 WebHost.CreateDefaultBuilderを使用して)は、 app.UseDeveloperExceptionPageを呼び出すことによって開発者例外ページを有効にすることができます。
Warnung
開発環境でアプリが実行されている場合を除き、開発者例外ページを有効にしないでください。 アプリが運用環境で実行されている場合は、詳細な例外情報をパブリックに共有しないでください。 環境の構成の詳細については、「 ASP.NET Core ランタイム環境」を参照してください。
開発者例外ページには、例外と要求に関する次の情報を含めることができます。
- スタック トレース
- クエリ文字列パラメーター (存在する場合)
- Cookie (存在する場合)
- Headers
- エンドポイント メタデータ (存在する場合)
開発者例外ページでは、情報が提供されるとは限りません。 ログ記録を使用して、完全なエラー情報を確認します。
次の図は、タブと表示される情報を示すアニメーションを含むサンプル開発者例外ページを示しています。
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
最小限の API で開発者例外ページを表示するには:
- 開発環境でサンプル アプリを実行します。
-
/exceptionエンドポイントに移動します。
このセクションでは、最小 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();
例外ハンドラー
開発環境以外では、 例外ハンドラー ミドルウェア を使用してエラー ペイロードを生成します。
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 クライアント (400-) またはサーバー (499500 -) 応答に対して、共通の本文コンテンツ (599) を生成するように構成できます。 ミドルウェアは、 UseStatusCodePages 拡張メソッドを呼び出すことによって構成されます。
たとえば、次の例では、ルーティング エラー ( など) を含むすべてのクライアントとサーバーの応答について、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);
問題の詳細
問題の詳細 は、HTTP API エラーを記述する唯一の応答形式ではありません。ただし、HTTP API のエラーを報告するために一般的に使用されます。
問題の詳細サービスは、 IProblemDetailsService インターフェイスを実装します。これは、ASP.NET Core での問題の詳細の作成をサポートします。
AddProblemDetails(IServiceCollection)のIServiceCollection拡張メソッドは、既定のIProblemDetailsService実装を登録します。
ASP.NET Core アプリでは、 AddProblemDetails が呼び出されたときに、次のミドルウェアによって問題の詳細 HTTP 応答が生成されます。ただし、 Accept 要求 HTTP ヘッダー に、登録された IProblemDetailsWriter でサポートされているコンテンツ タイプのいずれかが含まれていない場合 (既定値: application/json)。
- ExceptionHandlerMiddleware: カスタム ハンドラーが定義されていない場合に、問題の詳細応答を生成します。
- StatusCodePagesMiddleware: 既定で問題の詳細の応答を生成します。
-
DeveloperExceptionPageMiddleware:
Accept要求 HTTP ヘッダーにtext/htmlが含まれていない場合に、開発中に問題の詳細応答を生成します。
最小限の API アプリは、拡張メソッドを使用してすべての HTTP クライアントおよびサーバー エラー応答に対する問題の詳細応答を生成するように構成できます。
次のコードは、問題の詳細を生成するようにアプリを構成します。
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 に移行する場合:
- アクション フィルターをエンドポイント フィルターまたはミドルウェアに置き換える
- モデルの検証を手動検証またはカスタム バインドに置き換える
- 例外フィルターを例外処理ミドルウェアに置き換える
- 一貫性のあるエラー応答のためにを使用して
AddProblemDetails()する
コントローラー ベースのエラー処理を使用する場合
必要に応じて、コントローラー ベースの API を検討してください。
- 複雑なモデル検証シナリオ
- 複数のコントローラー間での一元的な例外処理
- エラー応答の書式設定をきめ細かく制御する
- フィルターや規則などの MVC 機能との統合
検証エラー、問題の詳細のカスタマイズ、例外フィルターなど、コントローラーベースのエラー処理の詳細については、「 コントローラー 」タブのセクションを参照してください。
その他のリソース
ASP.NET Core