はじめに
ウェブ上では壊れたリンクが数多く存在し、動作するページへのリダイレクトがない場合、ユーザーは非常に苛立たしく感じるでしょう。しかし、現実としてエラーは避けられません。ユーザーの誤った入力やコードのバグによって発生するエラーは、どうしても避けることができません。
本記事では、ASP.NET Core Webアプリケーションでカスタムエラーページを設定する最も効率的な方法を説明します。空白のページ、ブラウザ固有のデフォルトページ、ASP.NET Coreが提供するデフォルトのエラーページを使用するのとは対照的に、カスタムエラーページを使用することは、ユーザーエクスペリエンスを大幅に向上させます。
動作原理
アプリケーションを実行し、存在しないページにアクセスすると、リクエストがMVCパイプラインの最後まで到達し、リクエストを処理するミドルウェアがない場合、恐れ多い404エラー(または「ページが見つかりません」)が発生します。一部のブラウザは親切にエラーページを表示してくれますが、他のブラウザは空白のページを表示し、ユーザーを困惑させるだけです。これは、優れたユーザーエクスペリエンスを提供するものではありません。
カスタムエラーページの設定
コントローラークラスの作成
エラーページの設定を開始するには、リクエストに応答するコントローラーを作成する必要があります。この例を可能な限りシンプルにするために、シンプルなMVCコントローラークラスを作成します。Visual Studio(2015)が提供するデフォルトのテンプレートを使用し、ルート用のURIテンプレートを追加します。
public class ErrorHandlingController : Controller
{
// GET: /<controller>/
[HttpGet("/Error/{errorCode}")]
public IActionResult HandleError(int errorCode)
{
return View(errorCode);
}
}
より詳細な例として、ILoggerとIStatusCodeReExecuteFeatureインターフェースを使用してログを実装し、リクエストが通過したURLを記録することができます。
public class ErrorHandlingController : Controller
{
private readonly ILogger<ErrorHandlingController> _errorLogger;
public ErrorHandlingController(ILogger<ErrorHandlingController> logger)
{
_errorLogger = logger;
}
// GET: /<controller>/
[HttpGet("/Error/{errorCode}")]
public IActionResult HandleError(int errorCode)
{
var reExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
_errorLogger.LogError($"Error Occurred: {errorCode}, Request Path: {reExecuteFeature?.OriginalPath}");
return View(errorCode);
}
}
ビューの作成
次に、ErrorHandlingコントローラークラスのインデックスアクション用のビューを作成します。
シンプルなビューの場合、以下のようにできます。
@model int
<div class="error-container">
<h1>エラー @Model</h1>
<p>予期せぬ問題が発生しました</p>
</div>
より動的なビューにするには、さらに一歩進むことができます。
@model int
@{
var errorCode = Model;
var errorMessage = "";
switch (errorCode)
{
case 400:
errorMessage = "不正なリクエスト:構文エラーによりリクエストを処理できません";
break;
case 403:
errorMessage = "アクセスが拒否されました";
break;
case 404:
errorMessage = "ページが見つかりません";
break;
case 408:
errorMessage = "サーバーがリクエストの待機中にタイムアウトしました";
break;
case 500:
errorMessage = "内部サーバーエラー - サーバーがリクエストの処理を完了できませんでした";
break;
default:
errorMessage = "予期せぬ問題が発生しました";
break;
}
}
<div class="error-container">
<h1>エラー @Model</h1>
<p>@errorMessage</p>
</div>
HTTPステータスコードのケースをさらに追加することもできます。
ミドルウェアの設定
コントローラーとビューの準備ができたら、スタートアップクラスのconfigureメソッドでパイプライン内のリクエストを処理するミドルウェアを設定します。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
これで完了です!
結果
エラーページをテストするには、意図的にエラーを発生させることができます。存在しないページにアクセスして、404エラーを試してみましょう。