ASP.NET Core のエラーを処理する

作成者: Kirk LarkinTom DykstraSteve Smith

この記事では、ASP.NET Core Web アプリでエラーを処理するための一般的な手法について取り上げます。 Web API については、「ASP.NET Core Web API のエラーを処理する」 を参照してください。

開発者例外ページ

"開発者例外ページ" には、未処理の要求の例外に関する詳細な情報が表示されます。 開発環境で実行されている場合、ASP.NET Core アプリでは既定で開発者例外ページが有効になります。

開発者例外ページは、後続のミドルウェアでスローされた未処理の例外をキャッチできるように、ミドルウェア パイプラインの早い段階で実行されます。

アプリが運用環境で実行されている場合は、詳細な例外情報を公開しないようにしてください。 環境の構成について詳しくは、「ASP.NET Core で複数の環境を使用する」を参照してください。

開発者例外ページには、例外と要求に関する次の情報が含まれている場合があります。

  • スタック トレース
  • クエリ文字列のパラメーター (ある場合)
  • Cookie (ある場合)
  • ヘッダー

開発者例外ページで何らかの情報が提供されるとは限りません。 完全なエラー情報については、ログ記録に関するページを参照してください。

例外ハンドラー ページ

運用環境のカスタム エラー処理ページを構成するには、UseExceptionHandler を呼び出します。 この例外処理ミドルウェアは、次のことを行います。

  • 未処理の例外をキャッチしてログに記録します。
  • 指定されたパスを使用して、別のパイプラインで要求を再実行します。 応答が始まっていた場合、要求は再実行されません。 テンプレートによって生成されたコードは、/Error パスを使用して要求を再実行します。

警告

代替パイプラインで独自の例外がスローされた場合、例外処理ミドルウェアによって元の例外が再スローされます。

次の例では、UseExceptionHandler により非開発環境に例外処理ミドルウェアが追加されます。

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Razor Pages アプリのテンプレートには、エラー ページ (.cshtml) と PageModel クラス (ErrorModel) が Pages フォルダー内に用意されています。 MVC アプリの場合、プロジェクト テンプレートには、Home コントローラー用の Error アクション メソッドとエラー ビューが含まれています。

例外処理ミドルウェアでは、"元の" HTTP メソッドを使用して要求が再実行されます。 エラー ハンドラーのエンドポイントが特定の HTTP メソッドのセットに制限されている場合は、それらの HTTP メソッドに対してのみ実行されます。 たとえば、[HttpGet] 属性を使用する MVC コントローラーのアクションは、GET 要求に対してのみ実行されます。 "すべての" 要求がカスタム エラー処理ページに到達するようにするために、それらを特定の HTTP メソッドのセットに制限しないでください。

元の HTTP メソッドに応じて例外を異なる方法で処理するには:

  • Razor Pages の場合は、複数のハンドラー メソッドを作成します。 たとえば、GET 例外を処理するために OnGet を使用し、POST 例外を処理するために OnPost を使用します。
  • MVC の場合は、複数のアクションに HTTP 動詞属性を適用します。 たとえば、GET 例外を処理するために [HttpGet] を使用し、POST 例外を処理するために [HttpPost] を使用します。

認証されていないユーザーがカスタム エラー処理ページを表示できるようにするには、匿名アクセスがサポートされるようにします。

例外にアクセスする

エラー ハンドラーで例外や元の要求パスにアクセスするには、IExceptionHandlerPathFeature を使います。 次の例では、IExceptionHandlerPathFeature を使用して、スローされた例外に関する詳細を取得しています。

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
    public string? RequestId { get; set; }

    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

    public string? ExceptionMessage { get; set; }

    public void OnGet()
    {
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

        var exceptionHandlerPathFeature =
            HttpContext.Features.Get<IExceptionHandlerPathFeature>();

        if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
        {
            ExceptionMessage = "The file was not found.";
        }

        if (exceptionHandlerPathFeature?.Path == "/")
        {
            ExceptionMessage ??= string.Empty;
            ExceptionMessage += " Page: Home.";
        }
    }
}

警告

機密性の高いエラー情報をクライアントに提供しないでください。 エラーの提供はセキュリティ上のリスクです。

例外ハンドラー ラムダ

カスタム例外ハンドラー ページの代わりになるのは、UseExceptionHandler にラムダを提供することです。 ラムダを使うと、応答を返す前にエラーにアクセスできます。

次のコードは、例外処理にラムダを使用しています。

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler(exceptionHandlerApp =>
    {
        exceptionHandlerApp.Run(async context =>
        {
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;

            // using static System.Net.Mime.MediaTypeNames;
            context.Response.ContentType = Text.Plain;

            await context.Response.WriteAsync("An exception was thrown.");

            var exceptionHandlerPathFeature =
                context.Features.Get<IExceptionHandlerPathFeature>();

            if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
            {
                await context.Response.WriteAsync(" The file was not found.");
            }

            if (exceptionHandlerPathFeature?.Path == "/")
            {
                await context.Response.WriteAsync(" Page: Home.");
            }
        });
    });

    app.UseHsts();
}

警告

機密性の高いエラー情報をクライアントに提供しないでください。 エラーの提供はセキュリティ上のリスクです。

UseStatusCodePages

ASP.NET Core アプリでは、既定で、"404 - 見つかりません" などの HTTP エラー状態コードの状態コード ページが表示されません。 アプリで、本文のない HTTP 400 から 599 のエラー状態コードが設定されると、状態コードと空の応答本文が返されます。 一般的なエラー状態コード用に既定のテキスト専用ハンドラーを有効にするには、Program.csUseStatusCodePages を呼び出します。

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages();

要求処理ミドルウェアの前に UseStatusCodePages を呼び出します。 たとえば、静的ファイル ミドルウェアとエンドポイント ミドルウェアの前に UseStatusCodePages を呼び出します。

UseStatusCodePages を使用しない場合、エンドポイントなしで URL に移動すると、エンドポイントが見つからないことを示すブラウザー依存のエラー メッセージが返されます。 UseStatusCodePages が呼び出されると、ブラウザーにより次の応答が返されます。

Status Code: 404; Not Found

UseStatusCodePages は、ユーザーにとって役に立たないメッセージを返すため、通常は、運用環境では使用されません。

Note

状態コード ページのミドルウェアは例外をキャッチしません。 カスタム エラー処理ページを提供するには、例外ハンドラー ページを使用します。

書式設定文字列での UseStatusCodePages

応答の内容の種類とテキストをカスタマイズするには、内容の種類と書式文字列を受け取る UseStatusCodePages のオーバーロードを使います。

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

// using static System.Net.Mime.MediaTypeNames;
app.UseStatusCodePages(Text.Plain, "Status Code Page: {0}");

上記のコードでは、{0} はエラー コードのプレースホルダーです。

書式指定文字列を含む UseStatusCodePages は、ユーザーにとって役に立たないメッセージを返すため、通常は、運用環境では使用されません。

ラムダでの UseStatusCodePages

カスタム エラー処理と応答書き込みコードを指定するには、ラムダ式を受け取る UseStatusCodePages のオーバーロードを使います。

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages(async statusCodeContext =>
{
    // using static System.Net.Mime.MediaTypeNames;
    statusCodeContext.HttpContext.Response.ContentType = Text.Plain;

    await statusCodeContext.HttpContext.Response.WriteAsync(
        $"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});

ラムダを含む UseStatusCodePages は、ユーザーにとって役に立たないメッセージを返すため、通常は、運用環境では使用されません。

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects 拡張メソッド:

  • クライアントに 302 - Found 状態コードを送信します。
  • URL テンプレートで指定されているエラー処理エンドポイントにクライアントをリダイレクトします。 エラー処理エンドポイントには、通常、エラー情報が表示され、HTTP 200 が返されます。
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");

前のコードに示されているように、URL テンプレートには状態コード用の {0} プレースホルダーを含めることができます。 URL テンプレートが ~ (チルダ) で始まっている場合、~ はアプリの PathBase に置き換えられます。 アプリでエンドポイントを指定するときに、そのエンドポイントの MVC ビューまたは Razor ページを作成します。

この方法は、次のようなアプリで一般的に使用されます。

  • クライアントを別のエンドポイントにリダイレクトする必要がある場合 (通常は、別のアプリがエラーを処理する場合)。 Web アプリの場合は、クライアントのブラウザーのアドレス バーにリダイレクトされたエンドポイントが反映されます。
  • 元の状態コードを保持し、初回のリダイレクト応答で返してはいけない場合。

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute 拡張メソッド:

  • 元の状態コードをクライアントに返します。
  • 代替パスを使用して要求パイプラインを再実行することで、応答本文を生成します。
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");

アプリ内でエンドポイントが指定されている場合は、そのエンドポイントの MVC ビューまたは Razor ページを作成します。

この方法は、次のようなアプリで一般的に使用されます。

  • 別のエンドポイントにリダイレクトすることなく要求を処理する。 Web アプリの場合は、クライアントのブラウザーのアドレス バーに、初めに要求されていたエンドポイントが反映されます。
  • 元の状態コードを保持し、応答で返す。

URL テンプレートは / で始まる必要があります。このテンプレートには、状態コード用のプレースホルダー {0} を含めることができます。 状態コードをクエリ文字列パラメーターとして渡すには、2 番目の引数を UseStatusCodePagesWithReExecute に渡します。 次に例を示します。

app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");

次の例で示すように、エラーを処理するエンドポイントでは、エラーを生成した元の URL を取得できます。

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class StatusCodeModel : PageModel
{
    public int OriginalStatusCode { get; set; }

    public string? OriginalPathAndQuery { get; set; }

    public void OnGet(int statusCode)
    {
        OriginalStatusCode = statusCode;

        var statusCodeReExecuteFeature =
            HttpContext.Features.Get<IStatusCodeReExecuteFeature>();

        if (statusCodeReExecuteFeature is not null)
        {
            OriginalPathAndQuery = string.Join(
                statusCodeReExecuteFeature.OriginalPathBase,
                statusCodeReExecuteFeature.OriginalPath,
                statusCodeReExecuteFeature.OriginalQueryString);
        }
    }
}

状態コード ページを無効にする

MVC コントローラーまたはアクション メソッドの状態コード ページを無効にするには、[SkipStatusCodePages] 属性を使用します。

Razor Pages ハンドラー メソッドまたは MVC コントローラーの特定の要求に対して状態コード ページを無効にするには、IStatusCodePagesFeature を使用します。

public void OnGet()
{
    var statusCodePagesFeature =
        HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature is not null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

例外処理コード

例外処理ページのコードが例外をスローすることもあります。 運用環境のエラー ページは十分にテストし、それ自体から例外がスローされないように特に注意する必要があります。

応答ヘッダー

応答のヘッダーが送信された後は、次のようになります。

  • アプリで応答の状態コードを変更できません。
  • すべての例外ページやハンドラーを実行できません。 応答は完了している必要があります。あるいは、接続が中止となっている必要があります。

サーバー例外処理

アプリ内の例外処理ロジックに加えて、HTTP サーバーの実装でも一部の例外を処理できます。 応答ヘッダーの送信前にサーバーで例外がキャッチされると、サーバーによって "500 - Internal Server Error" 応答が応答本文なしで送信されます。 応答ヘッダーの送信後にサーバーで例外がキャッチされた場合、サーバーは接続を閉じます。 アプリで処理されない要求はサーバーで処理されます。 サーバーが要求を処理しているときに発生した例外は、すべてサーバーの例外処理によって処理されます。 この動作は、アプリのカスタム エラー ページ、例外処理ミドルウェア、およびフィルターから影響を受けません。

起動時の例外処理

アプリの起動中に起こる例外はホスティング層だけが処理できます。 起動時のエラーをキャプチャしたり、詳細なエラーをキャプチャしたりするように、ホストを構成することができます。

ホスティング レイヤーでは、ホスト アドレス/ポート バインド後にエラーが発生した場合にのみ、キャプチャされた起動時エラーに対するエラー ページを表示できます。 バインドが失敗した場合は、次のようになります。

  • ホスティング レイヤーにより重大な例外がログに記録されます。
  • dotnet プロセスがクラッシュします。
  • HTTP サーバーが Kestrel のときは、エラー ページは表示されません。

IIS (または Azure App Service) または IIS Express 上で実行している場合、プロセスを開始できなければ、ASP.NET Core モジュールから "502.5 - 処理エラー" が返されます。 詳細については、「Azure App Service および IIS での ASP.NET Core のトラブルシューティング」を参照してください。

データベース エラー ページ

データベース開発者ページ例外フィルター AddDatabaseDeveloperPageExceptionFilter では、Entity Framework Core の移行を使って解決できるデータベース関連の例外がキャプチャされます。 これらの例外が発生すると、問題が解決する可能性のあるアクションの詳細を含む HTML 応答が生成されます。 このページは、開発環境でのみ有効です。 次のコードでは、データベース開発者ページの例外フィルターを追加しています。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();

例外フィルター

MVC アプリでは、例外フィルターをグローバルに、またはコントローラーやアクションの単位で構成できます。 Razor Pages アプリでは、グローバルに、またはページ モデルの単位で構成できます。 このようなフィルターは、コントローラー アクションや別のフィルターの実行中に発生する未処理の例外を処理します。 詳細については、「ASP.NET Core フィルター」を参照してください。

例外フィルターは、MVC アクション内で発生する例外をトラップする場合には便利ですが、組み込みの例外処理ミドルウェアUseExceptionHandler ほど柔軟ではありません。 選択された MVC アクションに応じて異なる方法でエラー処理を実行する必要がある場合を除き、UseExceptionHandler を使用することをお勧めします。

モデル状態エラー

モデル状態エラーを処理する方法については、モデル バインドおよびモデルの検証に関する記事をご覧ください。

その他の技術情報

作成者: Kirk LarkinTom DykstraSteve Smith

この記事では、ASP.NET Core Web アプリでエラーを処理するための一般的な手法について取り上げます。 Web API については、「ASP.NET Core Web API のエラーを処理する」 を参照してください。

サンプル コードを表示またはダウンロードします。 (ダウンロード方法。)F12 ブラウザー開発者ツールの [ネットワーク] タブは、サンプル アプリをテストする場合に便利です。

開発者例外ページ

"開発者例外ページ" には、未処理の要求の例外に関する詳細な情報が表示されます。 ASP.NET Core テンプレートにより、次のコードが生成されます。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

前の強調表示されたコードは、アプリが開発環境で実行されている場合に、開発者例外ページを有効にします。

このテンプレートでは、後続のミドルウェアでスローされた未処理の例外をキャッチできるように、ミドルウェア パイプラインの早い段階で UseDeveloperExceptionPage が配置されます。

前のコードでは、アプリが開発環境で実行されている場合に "のみ"、開発者例外ページが有効になります。 アプリが運用環境で実行されている場合は、詳細な例外情報を公開しないようにしてください。 環境の構成について詳しくは、「ASP.NET Core で複数の環境を使用する」を参照してください。

開発者例外ページには、例外と要求に関する次の情報が含まれている場合があります。

  • スタック トレース
  • クエリ文字列のパラメーター (ある場合)
  • Cookie (ある場合)
  • ヘッダー

開発者例外ページで何らかの情報が提供されるとは限りません。 完全なエラー情報については、ログ記録に関するページを参照してください。

例外ハンドラー ページ

運用環境のカスタム エラー処理ページを構成するには、UseExceptionHandler を呼び出します。 この例外処理ミドルウェアは、次のことを行います。

  • 未処理の例外をキャッチしてログに記録します。
  • 指定されたパスを使用して、別のパイプラインで要求を再実行します。 応答が始まっていた場合、要求は再実行されません。 テンプレートによって生成されたコードは、/Error パスを使用して要求を再実行します。

警告

代替パイプラインで独自の例外がスローされた場合、例外処理ミドルウェアによって元の例外が再スローされます。

次の例では、UseExceptionHandler により非開発環境に例外処理ミドルウェアが追加されます。

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Razor Pages アプリのテンプレートには、エラー ページ (.cshtml) と PageModel クラス (ErrorModel) が Pages フォルダー内に用意されています。 MVC アプリの場合、プロジェクト テンプレートには、Home コントローラー用の Error アクション メソッドとエラー ビューが含まれています。

例外処理ミドルウェアでは、"元の" HTTP メソッドを使用して要求が再実行されます。 エラー ハンドラーのエンドポイントが特定の HTTP メソッドのセットに制限されている場合は、それらの HTTP メソッドに対してのみ実行されます。 たとえば、[HttpGet] 属性を使用する MVC コントローラーのアクションは、GET 要求に対してのみ実行されます。 "すべての" 要求がカスタム エラー処理ページに到達するようにするために、それらを特定の HTTP メソッドのセットに制限しないでください。

元の HTTP メソッドに応じて例外を異なる方法で処理するには:

  • Razor Pages の場合は、複数のハンドラー メソッドを作成します。 たとえば、GET 例外を処理するために OnGet を使用し、POST 例外を処理するために OnPost を使用します。
  • MVC の場合は、複数のアクションに HTTP 動詞属性を適用します。 たとえば、GET 例外を処理するために [HttpGet] を使用し、POST 例外を処理するために [HttpPost] を使用します。

認証されていないユーザーがカスタム エラー処理ページを表示できるようにするには、匿名アクセスがサポートされるようにします。

例外にアクセスする

エラー ハンドラーで例外や元の要求パスにアクセスするには、IExceptionHandlerPathFeature を使います。 次のコードは、ASP.NET Core テンプレートによって生成される既定の Pages/Error.cshtml.csExceptionMessage を追加します。

[ResponseCache(Duration=0, Location=ResponseCacheLocation.None, NoStore=true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
    public string RequestId { get; set; }
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
    public string ExceptionMessage { get; set; }
    private readonly ILogger<ErrorModel> _logger;

    public ErrorModel(ILogger<ErrorModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

        var exceptionHandlerPathFeature =
        HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
        {
            ExceptionMessage = "File error thrown";
            _logger.LogError(ExceptionMessage);
        }
        if (exceptionHandlerPathFeature?.Path == "/index")
        {
            ExceptionMessage += " from home page";
        }
    }
}

警告

機密性の高いエラー情報をクライアントに提供しないでください。 エラーの提供はセキュリティ上のリスクです。

サンプル アプリで例外をテストするには:

  • 環境を運用環境に設定します。
  • Program.cswebBuilder.UseStartup<Startup>(); からコメントを削除します。
  • ホーム ページで [Trigger an exception](例外をトリガーする) を選択します。

例外ハンドラー ラムダ

カスタム例外ハンドラー ページの代わりになるのは、UseExceptionHandler にラムダを提供することです。 ラムダを使うと、応答を返す前にエラーにアクセスできます。

次のコードは、例外処理にラムダを使用しています。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler(errorApp =>
        {
            errorApp.Run(async context =>
            {
                context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;;
                context.Response.ContentType = "text/html";

                await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
                await context.Response.WriteAsync("ERROR!<br><br>\r\n");

                var exceptionHandlerPathFeature =
                    context.Features.Get<IExceptionHandlerPathFeature>();

                if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
                {
                    await context.Response.WriteAsync(
                                              "File error thrown!<br><br>\r\n");
                }

                await context.Response.WriteAsync(
                                              "<a href=\"/\">Home</a><br>\r\n");
                await context.Response.WriteAsync("</body></html>\r\n");
                await context.Response.WriteAsync(new string(' ', 512)); 
            });
        });
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

警告

IExceptionHandlerFeature または IExceptionHandlerPathFeature からの機密性の高いエラー情報をクライアントに提供しないでください。 エラーの提供はセキュリティ上のリスクです。

サンプル アプリで例外処理ラムダをテストするには:

  • 環境を運用環境に設定します。
  • Program.cswebBuilder.UseStartup<StartupLambda>(); からコメントを削除します。
  • ホーム ページで [Trigger an exception](例外をトリガーする) を選択します。

UseStatusCodePages

ASP.NET Core アプリでは、既定で、"404 - 見つかりません" などの HTTP エラー状態コードの状態コード ページが表示されません。 アプリで、本文のない HTTP 400 から 599 のエラー状態コードが設定されると、状態コードと空の応答本文が返されます。 状態コード ページを提供するには、状態コード ページ ミドルウェアを使用します。 一般的なエラー状態コード用に既定のテキスト専用ハンドラーを有効にするには、Startup.Configure メソッドで UseStatusCodePages を呼び出します。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePages();

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

要求処理ミドルウェアの前に UseStatusCodePages を呼び出します。 たとえば、静的ファイル ミドルウェアとエンドポイント ミドルウェアの前に UseStatusCodePages を呼び出します。

UseStatusCodePages を使用しない場合、エンドポイントなしで URL に移動すると、エンドポイントが見つからないことを示すブラウザー依存のエラー メッセージが返されます。 たとえば、Home/Privacy2 に移動します。 UseStatusCodePages が呼び出されると、ブラウザーにより次が返されます。

Status Code: 404; Not Found

UseStatusCodePages は、ユーザーにとって役に立たないメッセージを返すため、通常は、運用環境では使用されません。

サンプル アプリUseStatusCodePages をテストするには:

  • 環境を運用環境に設定します。
  • Program.cswebBuilder.UseStartup<StartupUseStatusCodePages>(); からコメントを削除します。
  • ホーム ページにあるリンクを選択します。

Note

状態コード ページのミドルウェアは例外をキャッチしません。 カスタム エラー処理ページを提供するには、例外ハンドラー ページを使用します。

書式設定文字列での UseStatusCodePages

応答の内容の種類とテキストをカスタマイズするには、内容の種類と書式文字列を受け取る UseStatusCodePages のオーバーロードを使います。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePages(
        "text/plain", "Status code page, status code: {0}");

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

上記のコードでは、{0} はエラー コードのプレースホルダーです。

書式指定文字列を含む UseStatusCodePages は、ユーザーにとって役に立たないメッセージを返すため、通常は、運用環境では使用されません。

サンプル アプリUseStatusCodePages をテストするには、Program.cswebBuilder.UseStartup<StartupFormat>(); からコメントを削除します。

ラムダでの UseStatusCodePages

カスタム エラー処理と応答書き込みコードを指定するには、ラムダ式を受け取る UseStatusCodePages のオーバーロードを使います。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePages(async context =>
    {
        context.HttpContext.Response.ContentType = "text/plain";

        await context.HttpContext.Response.WriteAsync(
            "Status code page, status code: " +
            context.HttpContext.Response.StatusCode);
    });

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

ラムダを含む UseStatusCodePages は、ユーザーにとって役に立たないメッセージを返すため、通常は、運用環境では使用されません。

サンプル アプリUseStatusCodePages をテストするには、Program.cswebBuilder.UseStartup<StartupStatusLambda>(); からコメントを削除します。

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects 拡張メソッド:

  • クライアントに 302 - Found 状態コードを送信します。
  • URL テンプレートで指定されているエラー処理エンドポイントにクライアントをリダイレクトします。 エラー処理エンドポイントには、通常、エラー情報が表示され、HTTP 200 が返されます。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePagesWithRedirects("/MyStatusCode?code={0}");

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

前のコードに示されているように、URL テンプレートには状態コード用の {0} プレースホルダーを含めることができます。 URL テンプレートが ~ (チルダ) で始まっている場合、~ はアプリの PathBase に置き換えられます。 アプリでエンドポイントを指定するときに、そのエンドポイントの MVC ビューまたは Razor ページを作成します。 Razor Pages の例については、サンプル アプリにある Pages/MyStatusCode.cshtml をご覧ください。

この方法は、次のようなアプリで一般的に使用されます。

  • クライアントを別のエンドポイントにリダイレクトする必要がある場合 (通常は、別のアプリがエラーを処理する場合)。 Web アプリの場合は、クライアントのブラウザーのアドレス バーにリダイレクトされたエンドポイントが反映されます。
  • 元の状態コードを保持し、初回のリダイレクト応答で返してはいけない場合。

サンプル アプリUseStatusCodePages をテストするには、Program.cswebBuilder.UseStartup<StartupSCredirect>(); からコメントを削除します。

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute 拡張メソッド:

  • 元の状態コードをクライアントに返します。
  • 代替パスを使用して要求パイプラインを再実行することで、応答本文を生成します。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePagesWithReExecute("/MyStatusCode2", "?code={0}");

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

アプリ内でエンドポイントが指定されている場合は、そのエンドポイントの MVC ビューまたは Razor ページを作成します。 UseRouting の前に UseStatusCodePagesWithReExecute が配置されていることを確認して、要求を状態ページに再ルーティングできるようにします。 Razor Pages の例については、サンプル アプリにある Pages/MyStatusCode2.cshtml をご覧ください。

この方法は、次のようなアプリで一般的に使用されます。

  • 別のエンドポイントにリダイレクトすることなく要求を処理する。 Web アプリの場合は、クライアントのブラウザーのアドレス バーに、初めに要求されていたエンドポイントが反映されます。
  • 元の状態コードを保持し、応答で返す。

URL とクエリ文字列のテンプレートには、状態コード用のプレースホルダー {0} を含めることができます。 URL テンプレートの先頭には、/ を付ける必要があります。

次の例で示すように、エラーを処理するエンドポイントでは、エラーを生成した元の URL を取得できます。

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class MyStatusCode2Model : PageModel
{
    public string RequestId { get; set; }
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

    public string ErrorStatusCode { get; set; }

    public string OriginalURL { get; set; }
    public bool ShowOriginalURL => !string.IsNullOrEmpty(OriginalURL);

    public void OnGet(string code)
    {
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
        ErrorStatusCode = code;

        var statusCodeReExecuteFeature = HttpContext.Features.Get<
                                               IStatusCodeReExecuteFeature>();
        if (statusCodeReExecuteFeature != null)
        {
            OriginalURL =
                statusCodeReExecuteFeature.OriginalPathBase
                + statusCodeReExecuteFeature.OriginalPath
                + statusCodeReExecuteFeature.OriginalQueryString;
        }
    }
}

Razor Pages の例については、サンプル アプリにある Pages/MyStatusCode2.cshtml をご覧ください。

サンプル アプリUseStatusCodePages をテストするには、Program.cswebBuilder.UseStartup<StartupSCreX>(); からコメントを削除します。

状態コード ページを無効にする

MVC コントローラーまたはアクション メソッドの状態コード ページを無効にするには、[SkipStatusCodePages] 属性を使用します。

Razor Pages ハンドラー メソッドまたは MVC コントローラーの特定の要求に対して状態コード ページを無効にするには、IStatusCodePagesFeature を使用します。

public void OnGet()
{
    // using Microsoft.AspNetCore.Diagnostics;
    var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature != null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

例外処理コード

例外処理ページのコードが例外をスローすることもあります。 運用環境のエラー ページは十分にテストし、それ自体から例外がスローされないように特に注意する必要があります。

応答ヘッダー

応答のヘッダーが送信された後は、次のようになります。

  • アプリで応答の状態コードを変更できません。
  • すべての例外ページやハンドラーを実行できません。 応答は完了している必要があります。あるいは、接続が中止となっている必要があります。

サーバー例外処理

アプリ内の例外処理ロジックに加えて、HTTP サーバーの実装でも一部の例外を処理できます。 応答ヘッダーの送信前にサーバーで例外がキャッチされると、サーバーによって "500 - Internal Server Error" 応答が応答本文なしで送信されます。 応答ヘッダーの送信後にサーバーで例外がキャッチされた場合、サーバーは接続を閉じます。 アプリで処理されない要求はサーバーで処理されます。 サーバーが要求を処理しているときに発生した例外は、すべてサーバーの例外処理によって処理されます。 この動作は、アプリのカスタム エラー ページ、例外処理ミドルウェア、およびフィルターから影響を受けません。

起動時の例外処理

アプリの起動中に起こる例外はホスティング層だけが処理できます。 起動時のエラーをキャプチャしたり、詳細なエラーをキャプチャしたりするように、ホストを構成することができます。

ホスティング レイヤーでは、ホスト アドレス/ポート バインド後にエラーが発生した場合にのみ、キャプチャされた起動時エラーに対するエラー ページを表示できます。 バインドが失敗した場合は、次のようになります。

  • ホスティング レイヤーにより重大な例外がログに記録されます。
  • dotnet プロセスがクラッシュします。
  • HTTP サーバーが Kestrel のときは、エラー ページは表示されません。

IIS (または Azure App Service) または IIS Express 上で実行している場合、プロセスを開始できなければ、ASP.NET Core モジュールから "502.5 - 処理エラー" が返されます。 詳細については、「Azure App Service および IIS での ASP.NET Core のトラブルシューティング」を参照してください。

データベース エラー ページ

データベース開発者ページ例外フィルター AddDatabaseDeveloperPageExceptionFilter では、Entity Framework Core の移行を使って解決できるデータベース関連の例外がキャプチャされます。 これらの例外が発生すると、問題が解決する可能性のあるアクションの詳細を含む HTML 応答が生成されます。 このページは、開発環境でのみ有効です。 次のコードは、個々のユーザー アカウントが指定されたときに、ASP.NET Core Razor Pages テンプレートによって生成されたものです。

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();
}

例外フィルター

MVC アプリでは、例外フィルターをグローバルに、またはコントローラーやアクションの単位で構成できます。 Razor Pages アプリでは、グローバルに、またはページ モデルの単位で構成できます。 このようなフィルターは、コントローラー アクションや別のフィルターの実行中に発生する未処理の例外を処理します。 詳細については、「ASP.NET Core フィルター」を参照してください。

例外フィルターは、MVC アクション内で発生する例外をトラップする場合には便利ですが、組み込みの例外処理ミドルウェアUseExceptionHandler ほど柔軟ではありません。 選択された MVC アクションに応じて異なる方法でエラー処理を実行する必要がある場合を除き、UseExceptionHandler を使用することをお勧めします。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

モデル状態エラー

モデル状態エラーを処理する方法については、モデル バインドおよびモデルの検証に関する記事をご覧ください。

その他の技術情報

作成者: Tom DykstraSteve Smith

この記事では、ASP.NET Core Web アプリでエラーを処理するための一般的な手法について取り上げます。 Web API については、「ASP.NET Core Web API のエラーを処理する」 を参照してください。

サンプル コードを表示またはダウンロードします。 (ダウンロード方法。)

開発者例外ページ

"開発者例外ページ" には、要求の例外に関する詳細な情報が表示されます。 ASP.NET Core テンプレートにより、次のコードが生成されます。

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

前のコードは、アプリが開発環境で実行されている場合に、開発者例外ページを有効にします。

このテンプレートでは、後続のミドルウェアで例外をキャッチできるように、ミドルウェアの前に UseDeveloperExceptionPage が配置されます。

前のコードは、アプリが開発環境で実行されている場合にのみ、開発者例外ページを有効にします。 アプリが運用環境で実行されている場合は、詳細な例外情報を公開しないようにしてください。 環境の構成について詳しくは、「ASP.NET Core で複数の環境を使用する」を参照してください。

開発者例外ページには、例外と要求に関する次の情報が含まれています。

  • スタック トレース
  • クエリ文字列のパラメーター (ある場合)
  • Cookie (ある場合)
  • ヘッダー

例外ハンドラー ページ

運用環境用のカスタム エラー処理ページを構成するには、例外処理ミドルウェアを使用します。 ミドルウェアでは次を行います。

  • 例外をキャッチしてログに記録します。
  • ページ用の、またはコントローラーが指定した別のパイプラインで、要求を再実行します。 応答が始まっていた場合、要求は再実行されません。 テンプレートによって生成されたコードは、/Error への要求を再実行します。

次の例では、UseExceptionHandler により非開発環境に例外処理ミドルウェアが追加されます。

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Razor Pages アプリのテンプレートには、エラー ページ ( .cshtml) と PageModel クラス (ErrorModel) が Pages フォルダー内に用意されています。 MVC アプリの場合、プロジェクト テンプレートには、Home コントローラーのエラー アクション メソッドとエラー ビューが含まれています。

HttpGet などの HTTP メソッド属性を使ってエラー ハンドラー アクション メソッドをマークしないでください。 明示的な動詞を使用すると、要求がメソッドに届かないことがあります。 認証されていないユーザーにエラー ビューが表示される場合は、メソッドへの匿名アクセスを許可します。

例外にアクセスする

エラー ハンドラー コントローラーまたはページ内で例外や元の要求パスにアクセスするには、IExceptionHandlerPathFeature を使います。

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel
{
    public string RequestId { get; set; }
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
    public string ExceptionMessage { get; set; }

    public void OnGet()
    {
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

        var exceptionHandlerPathFeature =
            HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
        {
            ExceptionMessage = "File error thrown";
        }
        if (exceptionHandlerPathFeature?.Path == "/index")
        {
            ExceptionMessage += " from home page";
        }
    }
}

警告

機密性の高いエラー情報をクライアントに提供しないでください。 エラーの提供はセキュリティ上のリスクです。

上記の例外処理ページをトリガーするには、環境を運用に設定し、例外を強制します。

例外ハンドラー ラムダ

カスタム例外ハンドラー ページの代わりになるのは、UseExceptionHandler にラムダを提供することです。 ラムダを使うと、応答を返す前にエラーにアクセスできます。

例外処理にラムダを使う例を次に示します。

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
   app.UseExceptionHandler(errorApp =>
   {
        errorApp.Run(async context =>
        {
            context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
            context.Response.ContentType = "text/html";

            await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
            await context.Response.WriteAsync("ERROR!<br><br>\r\n");

            var exceptionHandlerPathFeature = 
                context.Features.Get<IExceptionHandlerPathFeature>();

            if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
            {
                await context.Response.WriteAsync("File error thrown!<br><br>\r\n");
            }

            await context.Response.WriteAsync("<a href=\"/\">Home</a><br>\r\n");
            await context.Response.WriteAsync("</body></html>\r\n");
            await context.Response.WriteAsync(new string(' ', 512)); // IE padding
        });
    });
    app.UseHsts();
}

上記のコードでは await context.Response.WriteAsync(new string(' ', 512)); が追加されるため、Internet Explorer ブラウザーには IE のエラー メッセージではなく、このエラー メッセージが表示されます。 詳細については、次を参照してください。この GitHub の問題します。

警告

IExceptionHandlerFeature または IExceptionHandlerPathFeature からの機密性の高いエラー情報をクライアントに提供しないでください。 エラーの提供はセキュリティ上のリスクです。

サンプル アプリで例外処理ラムダの結果を表示するには、ProdEnvironment および ErrorHandlerLambda プリプロセッサ ディレクティブを使用して、ホーム ページで [Trigger an exception](例外をトリガーする) を選択します。

UseStatusCodePages

ASP.NET Core アプリでは、既定で、"404 - 見つかりません" などの HTTP 状態コードの状態コード ページが表示されません。 アプリでは、状態コードと空の応答本文が返されます。 状態コード ページを提供するには、状態コード ページ ミドルウェアを使用します。

そのミドルウェアは、Microsoft.AspNetCore.Diagnostics パッケージによって使用可能になります。

一般的なエラー状態コード用に既定のテキスト専用ハンドラーを有効にするには、Startup.Configure メソッドで UseStatusCodePages を呼び出します。

app.UseStatusCodePages();

要求処理ミドルウェア (たとえば、静的ファイル ミドルウェアや MVC ミドルウェア) の前に UseStatusCodePages を呼び出します。

UseStatusCodePages を使用しない場合、エンドポイントなしで URL に移動すると、エンドポイントが見つからないことを示すブラウザー依存のエラー メッセージが返されます。 たとえば、Home/Privacy2 に移動します。 UseStatusCodePages が呼び出されると、ブラウザーにより次が返されます。

Status Code: 404; Not Found

書式設定文字列での UseStatusCodePages

応答の内容の種類とテキストをカスタマイズするには、内容の種類と書式文字列を受け取る UseStatusCodePages のオーバーロードを使います。

app.UseStatusCodePages(
    "text/plain", "Status code page, status code: {0}");

ラムダでの UseStatusCodePages

カスタム エラー処理と応答書き込みコードを指定するには、ラムダ式を受け取る UseStatusCodePages のオーバーロードを使います。

app.UseStatusCodePages(async context =>
{
    context.HttpContext.Response.ContentType = "text/plain";

    await context.HttpContext.Response.WriteAsync(
        "Status code page, status code: " + 
        context.HttpContext.Response.StatusCode);
});

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects 拡張メソッド:

  • クライアントに 302 - Found 状態コードを送信します。
  • URL テンプレートで指定された場所にクライアントをリダイレクトします。
app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");

次の例で示すように、URL テンプレートには状態コード用の {0} プレースホルダーを含めることができます。 URL テンプレートが ~ (チルダ) で始まっている場合、~ はアプリの PathBase に置き換えられます。 アプリ内でエンドポイントを指し示す場合は、そのエンドポイントの MVC ビューまたは Razor ページを作成します。 Razor Pages の例については、サンプル アプリにある Pages/StatusCode.cshtml をご覧ください。

この方法は、次のようなアプリで一般的に使用されます。

  • クライアントを別のエンドポイントにリダイレクトする必要がある場合 (通常は、別のアプリがエラーを処理する場合)。 Web アプリの場合は、クライアントのブラウザーのアドレス バーにリダイレクトされたエンドポイントが反映されます。
  • 元の状態コードを保持し、初回のリダイレクト応答で返してはいけない場合。

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute 拡張メソッド:

  • 元の状態コードをクライアントに返します。
  • 代替パスを使用して要求パイプラインを再実行することで、応答本文を生成します。
app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");

アプリ内でエンドポイントを指し示す場合は、そのエンドポイントの MVC ビューまたは Razor ページを作成します。 UseRouting の前に UseStatusCodePagesWithReExecute が配置されていることを確認して、要求を状態ページに再ルーティングできるようにします。 Razor Pages の例については、サンプル アプリにある Pages/StatusCode.cshtml をご覧ください。

この方法は、次のようなアプリで一般的に使用されます。

  • 別のエンドポイントにリダイレクトすることなく要求を処理する。 Web アプリの場合は、クライアントのブラウザーのアドレス バーに、初めに要求されていたエンドポイントが反映されます。
  • 元の状態コードを保持し、応答で返す。

URL とクエリ文字列のテンプレートには、状態コード用のプレースホルダー ({0}) を含めることができます。 URL テンプレートの先頭には、スラッシュ (/) を付ける必要があります。 パスでプレースホルダーを使う場合は、エンドポイント (ページまたはコントローラー) でパスのセグメントを処理できることを確認します。 たとえば、エラー用の Razor ページでは、@page ディレクティブの付いた省略可能なパスのセグメント値を受け入れる必要があります。

@page "{code?}"

次の例で示すように、エラーを処理するエンドポイントでは、エラーを生成した元の URL を取得できます。

var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
    OriginalURL =
        statusCodeReExecuteFeature.OriginalPathBase
        + statusCodeReExecuteFeature.OriginalPath
        + statusCodeReExecuteFeature.OriginalQueryString;
}

HttpGet などの HTTP メソッド属性を使ってエラー ハンドラー アクション メソッドをマークしないでください。 明示的な動詞を使用すると、要求がメソッドに届かないことがあります。 認証されていないユーザーにエラー ビューが表示される場合は、メソッドへの匿名アクセスを許可します。

状態コード ページを無効にする

MVC コントローラーまたはアクション メソッドの状態コード ページを無効にするには、[SkipStatusCodePages] 属性を使用します。

Razor Pages ハンドラー メソッドまたは MVC コントローラーの特定の要求に対して状態コード ページを無効にするには、IStatusCodePagesFeature を使用します。

var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();

if (statusCodePagesFeature != null)
{
    statusCodePagesFeature.Enabled = false;
}

例外処理コード

例外処理ページのコードは例外をスローすることがあります。 実稼働のエラー ページは純粋に静的なコンテンツで構成することをお勧めします。

応答ヘッダー

応答のヘッダーが送信された後は、次のようになります。

  • アプリで応答の状態コードを変更できません。
  • すべての例外ページやハンドラーを実行できません。 応答は完了している必要があります。あるいは、接続が中止となっている必要があります。

サーバー例外処理

アプリ内の例外処理ロジックに加えて、HTTP サーバーの実装でも一部の例外を処理できます。 応答ヘッダーの送信前にサーバーで例外がキャッチされると、サーバーによって "500 - 内部サーバー エラーです" 応答が応答本文なしで送信されます。 応答ヘッダーの送信後にサーバーで例外がキャッチされた場合、サーバーは接続を閉じます。 アプリで処理されない要求はサーバーで処理されます。 サーバーが要求を処理しているときに発生した例外は、すべてサーバーの例外処理によって処理されます。 この動作は、アプリのカスタム エラー ページ、例外処理ミドルウェア、およびフィルターから影響を受けません。

起動時の例外処理

アプリの起動中に起こる例外はホスティング層だけが処理できます。 起動時のエラーをキャプチャしたり、詳細なエラーをキャプチャしたりするように、ホストを構成することができます。

ホスティング レイヤーでは、ホスト アドレス/ポート バインド後にエラーが発生した場合にのみ、キャプチャされた起動時エラーに対するエラー ページを表示できます。 バインドが失敗した場合は、次のようになります。

  • ホスティング レイヤーにより重大な例外がログに記録されます。
  • dotnet プロセスがクラッシュします。
  • HTTP サーバーが Kestrel のときは、エラー ページは表示されません。

IIS (または Azure App Service) または IIS Express 上で実行している場合、プロセスを開始できなければ、ASP.NET Core モジュールから "502.5 - 処理エラー" が返されます。 詳細については、「Azure App Service および IIS での ASP.NET Core のトラブルシューティング」を参照してください。

データベース エラー ページ

データベース エラー ページ ミドルウェアでは、Entity Framework の移行を使って解決できるデータベース関連の例外がキャプチャされます。 これらの例外が発生すると、問題が解決する可能性のあるアクションの詳細を含む HTML 応答が生成されます。 このページは、開発環境でのみ有効にする必要があります。 ページを有効にするには、コードを Startup.Configure に追加します。

if (env.IsDevelopment())
{
    app.UseDatabaseErrorPage();
}

UseDatabaseErrorPage には、Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet パッケージが必要です。

例外フィルター

MVC アプリでは、例外フィルターをグローバルに、またはコントローラーやアクションの単位で構成できます。 Razor Pages アプリでは、グローバルに、またはページ モデルの単位で構成できます。 このようなフィルターはコントローラー アクションや別のフィルターの実行中に発生する未処理の例外を処理します。 詳細については、「ASP.NET Core フィルター」を参照してください。

ヒント

例外フィルターは、MVC アクション内で発生した例外をトラップする場合は便利ですが、例外処理ミドルウェアほど柔軟ではありません。 ミドルウェアの使用をお勧めします。 選択された MVC アクションに応じて異なる方法でエラー処理を実行する必要がある場合にのみ、フィルターを使用します。

モデル状態エラー

モデル状態エラーを処理する方法については、モデル バインドおよびモデルの検証に関する記事をご覧ください。

その他の技術情報