エラーが起きたらどうなるか? Application_Error()と、HandleErrorAttribute
MVCでカスタムエラーページを実装しようとした時、
調べると以下の2つのコードに到着すると思います。
- Web.Config にて
<customErrors mode="On" defaultRedirect="~/Error/ErrorDayo" > </customErrors>
- Glogal.asax.cs にて
filters.Add(new HandleErrorAttribute()); // (またはControllerクラスにて [HandleError])
これらの実装は、ASP.NET の機能と、ASP.NET MVC の機能、2つの要素が関わっています。
この2つを区別しないと、思った通りにエラーページが表示されなかったり、
エラー時の対応処理を行えない場合があります。
今日は、この2つを区別するために、
エラーが起きた時、どのような流れでエラーページに行くのか、
確認してみようと思います。
CustomErrors mode = "On" の時
前提
以下のようにした場合の、エラー時の流れを追います。
Web.Config
<customErrors mode="On" defaultRedirect="~/Error/ErrorDayo" > </customErrors>
Glogal.asax.cs
filters.Add(new HandleErrorAttribute());
1. "On" & MVCのパイプライン内(Controller内)でエラー発生時
- 1. 例えば、Controllerのアクションメソッド内にてエラーが発生。
- 2. フィルター属性HandleErrorAttributeクラスの、OnExceptionメソッドへ。
- 3. OnExceptionメソッド内では、"Error"というViewを返すよう記述してある。
- 4. "Error"というViewを探し、ユーザにエラーページが出力される。
流れは以上です。MVCでの一般的なエラー対処です。
この時のポイントは3つあります。
- エラーページは、リダイレクトで表示されたものではない。
- WebConfigで設定したdefaultRedirect="~/Error/ErrorDayo" は全く関係ない。
- Global.asax(HttpApplication)の、Application_Error()メソッドは呼び出されない。
↓おまけのMVCソースコード、OnExceptionメソッド内の一部。
filterContext.Result = new ViewResult { ViewName = View, //← デフォルトでは"Error" MasterName = Master, ViewData = new ViewDataDictionary<HandleErrorInfo>(model), TempData = filterContext.Controller.TempData };
↓同じくOnExceptionメソッド内のなんだか怪しいコード
// Certain versions of IIS will sometimes use their own error page when // they detect a server error. Setting this property indicates that we // want it to try to render ASP.NET MVC's error page instead. filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
2. "On" & MVCのパイプライン以外のエラー発生時
次は、Controller以外でエラーが発生した時です。
- 1. 例えば、カスタムControllerFactory内にてエラーが発生。
- 2. Global.asaxのApplication_Error()メソッドへ。
- 3. WebConfigで、mode="On" defaultRedirect="~/Error/ErrorDayo" と書いてあるので、~/Error/ErrorDayoへリダイレクト
- 4. ~/Error/ErrorDayoへアクセスされたので、それに対応するコントローラのアクションメソッドが実行される
- 5. ちゃんとアクションメソッドとViewが実装されていれば、エラーページ表示でめでたし。
流れは以上です。
ポイントは3つあります。
- defaultRedirectに設定したURLにリダイレクトすることで、エラーページが表示される。
- フィルター属性HandleErrorAttributeクラスは、関係ない。
- エラーページを表示するために、普段と同じようコントローラとViewが呼び出される。(静的な.Htmlも呼び出し可能)
CustomErrors mode = "Off" の時
前提
次は、WebConfigにて、CustomErrors mode = "Off" と設定した時の流れを追います。
先ほどのOnと同じく、HandleErrorAttributeクラスは登録したものとします。
3. "Off" & MVCのパイプライン内(Controller内)でエラー発生時
- 1. 例えば、Controllerのアクションメソッド内にてエラーが発生。
- 2. フィルター属性HandleErrorAttributeクラスの、OnExceptionメソッドへ。
- 3. OnExceptionメソッド内では、"Error"というViewを返すよう記述してある。
- 4. でも、CustomErrors mode = "Off"がそれを許してくれない。
- 5. Global.asaxのApplication_Error()メソッドへ。
- 6. IISのエラーページが表示される。
ポイントは
- CustomErrors mode = "Off" でも、HandleErrorAttributeクラスに処理が行く事。
です。
おしまい。
以上、エラー発生時の流れを追ってみました。
覚えておきたいことは、下の4つです。
- HandleErrorAttributeクラスは、MVCフレームワークの機能であること
- そして、エラーを扱うけど、元はただのフィルター属性であること
- WebConfigのCustomErrors は、MVCではなくASP.NETの機能であること
- WebConfigのdefaultRedirectは、URLにリダイレクトする、というWEBの機能を利用していること
当たり前のことばかりだと思いますが、ノービスな私にとっては、
カスタムエラーページの理解は、ゴチャゴチャしていたものでしたorz
ちゃんと理解すれば、私みたいにエラーなのに処理してくれない! なんか対応処理が2回起こった!
という状態にならなくて済みます。⊂⌒~⊃。Д。)⊃