Error Handling - 日本語意訳

- 2017/07/29(Sat) 時点の情報に基づいています
- 公式ドキュメント：[Error Handling](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/error-handling)

# ASP.NET Core のエラー処理の概要

この記事では、ASP.NET Core アプリケーションのエラー処理の一般的な方法について説明します。

[サンプルコードの表示またはダウンロード](https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/error-handling/sample)

## 開発者例外ページ

例外に関する詳細情報を表示するページを表示するようにアプリを設定するには、`Microsoft.AspNetCore.Diagnostics` NuGet パッケージをインストールし、[Startup クラスの Configure メソッド](startup.md) に1行を追加します:

```csharp:C#
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();
    env.EnvironmentName = EnvironmentName.Production;
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error");
    }
```

`app.UseMvc` など、例外をキャッチしたい Middleware の前に `UseDeveloperExceptionPage` を配置します。

>[!警告]
> **アプリが開発環境で実行されているときのみ**、開発者例外ページを有効にしてください。アプリが本番環境で実行されているときに、詳細な例外情報を公開する必要はありません。[環境設定の詳細については、こちらをご覧ください](environments.md).

開発者例外ページを表示するには、環境を `Development` に設定してサンプルアプリケーションを実行し、`?throw=true` をアプリのベースURLに追加します。このページには、例外とリクエストに関する情報を含むいくつかのタブが含まれています。最初のタブにはスタックトレースが含まれています。

![Stack trace](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/error-handling/_static/developer-exception-page.png)

次のタブには、クエリ文字列パラメータがあれば表示されます。

![Query string parameters](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/error-handling/_static/developer-exception-page-query.png)

このリクエストには Cookie は含まれていませんでしたが、もしあれば **Cookies** タブに表示されます。最後のタブには、渡されたヘッダーが表示されます。

![Headers](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/error-handling/_static/developer-exception-page-headers.png)

## カスタム例外処理ページの構成

アプリが `Development` 環境で実行されていないときには、例外処理ページを構成して使用すると良いでしょう。

```csharp:C#
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();
    env.EnvironmentName = EnvironmentName.Production;
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error");
    }
```
MVC アプリケーションでは、`HttpGet` などの HTTP メソッド属性を使用して、エラーハンドラーのアクションメソッドを明示的に修飾しないでください。明示的な動詞を使用すると、いくつかのリクエストがメソッドに到達するのを防ぐことができます。

```csharp:C#
[Route("/Error")]
public IActionResult Index()
{
    // Handle error here
}
```

## ステータスコードページの構成

デフォルトでは、アプリケーションでは、500 (Internal Server Error）や 404 (Not Found) などの HTTP ステータスコードのリッチなステータスコードページは提供されません。以下の行を `Configure` メソッドに追加して `StatusCodePagesMiddleware` を構成することができます：

```csharp:C#
app.UseStatusCodePages();
```

デフォルトでは、この Middleware は、404 などの一般的なステータスコード用のシンプルなテキストだけのハンドラを追加します。

![404 page](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/error-handling/_static/default-404-status-code.png)

この Middleware は、いくつかの異なる拡張メソッドをサポートしています。1つはラムダ式をとり、もう1つはコンテンツタイプとフォーマット文字列をとります。

```csharp:C#
app.UseStatusCodePages(async context =>
{
    context.HttpContext.Response.ContentType = "text/plain";
    await context.HttpContext.Response.WriteAsync(
        "Status code page, status code: " + 
        context.HttpContext.Response.StatusCode);
});
```
```csharp:C#
app.UseStatusCodePages("text/plain", "Status code page, status code: {0}");
```

リダイレクト拡張メソッドもあります。1つは 302 ステータスコードをクライアントに送信し、もう1つは元のステータスコードをクライアントに返しますがリダイレクト URL のハンドラも実行します。

```csharp:C#
app.UseStatusCodePagesWithRedirects("/error/{0}");
```

```csharp:C#
app.UseStatusCodePagesWithReExecute("/error/{0}");
```

特定のリクエストに対してステータスコードページを無効にする必要がある場合は、次のようにします：

```csharp:C#
var statusCodePagesFeature = context.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
  statusCodePagesFeature.Enabled = false;
}
```

## 例外処理コード

例外処理ページ中のコードは例外をスローする可能性があります。本番環境でのエラーページは純粋な静的コンテンツで構成するのが良いでしょう。

また、レスポンスヘッダーが送信されたら、レスポンスのステータスコードを変更することも、例外ページやハンドラを実行することもできないことに注意してください。レスポンスを完了するか、接続を中断しなければなりません。

## サーバー例外処理

例外処理ロジックに加えて、[サーバー](servers/index.md) はいくつかの例外処理を行います。もしヘッダー送信前にサーバーが例外をキャッチした場合、500 Internal Server Error でボディなしのレスポンスを送信します。もしヘッダー送信後にエラーをキャッチした場合、接続を閉じます。アプリケーションで処理されないリクエストはサーバーによって処理され、発生した例外はサーバーの例外処理によって処理されます。アプリケーション用に設定したカスタムエラーページや例外処理 Middleware やフィルターは、この動作に影響しません。

## スタートアップ例外処理

アプリケーションの起動中に発生する例外は、ホスティングレイヤーだけが処理できます。アプリケーションの起動中に発生する例外はサーバーの動作に影響を与える可能性があります。例えば、もし `KestrelServerOptions.UseHttps` の実行前に例外が発生した場合、ホスティングレイヤーが例外をキャッチし、サーバーを起動し、SSL でないポートにエラーページを表示します。もしその行が実行された後に例外が発生した場合、エラーページは HTTPS で表示されます。

`CaptureStartupErrors` と `detailedErrors` キーを使用して、[起動中のエラーに応じてホストがどのように動作するかを設定](hosting.md#configuring-a-host)できます。

## ASP.NET MVC エラー処理

[MVC](../mvc/index.md) アプリケーションには、例外フィルターの構成やモデル検証の実行など、エラー処理のためのいくつかの追加オプションを持っています。

### 例外フィルター

例外フィルターは、MVC アプリケーションでグローバルに、またはコントローラごとまたはアクションごとに構成できます。これらのフィルターは、コントローラアクションまたは別のフィルターの実行中に発生した未処理の例外を処理し、それ以外の場合は実行されません。[フィルター](../mvc/controllers/filters.md)の例外フィルターについて、詳しくはこちらをご覧ください。

>[!TIP]
> 例外フィルターは、MVC アクション内で発生する例外を捕捉するのに適していますが、エラー処理 Middleware ほど柔軟ではありません。通常の場合には Middleware を使用し、MVC アクションが選択されたことに基づいて　*異なる* 処理を行う必要がある場合にのみフィルターを使用しましょう。

### モデル状態エラーの処理

[モデル検証](../mvc/models/validation.md) は各コントローラーアクションが実行される前に起こり、
 `ModelState.IsValid` を検査して適切に反応するのはアクションメソッドの責任です。

一部のアプリでは、モデルの検証エラーを処理するための標準的な規約に従うことを選択します。この場合、[フィルター](../mvc/controllers/filters.md)はそのようなポリシーを実装するのに適した場所です。無効なモデル状態でアクションがどのように動作するかをテストする必要があります。[コントローラロジックのテスト](../mvc/controllers/testing.md) で詳しく学んでください。