エラーのステータスコードを返す時の httpErrors の設定内容について

前回のポストで

ASP.NET MVC のページ内での jQuery を使った Controller アクセスの結果を http status code を使って表そうという試みを最後に行ったのだが、それを試しに IIS にデプロイしてみると Visual Studio 上でのデバッグ環境とは異なる挙動をする事が分かった。

簡単に言うと、http status code が 400 以上の場合に一緒に返却した json レスポンスが「要求されたサイトは存在しません」的なメッセージに書き換えられて返却されてしまうというもの。(ちなみに環境は IIS 7.5 です。)

何が起こっているのか?

挙動の理由は簡単で、私の作ったサンプルは全て Web.config がデフォルトであり、私のPC の IIS のエラーに関する設定もデフォルトであったため、デフォルト通りの挙動をしたというだけのようである。

httpErros 要素

http://technet.microsoft.com/ja-jp/library/ee431601.aspx

詳細は上記ページを参照してもらう方が分かりやすいが、httpErrors 要素ではサイトやアプリケーションで HTTPエラーが発生した、させた場合にカスタムのエラーメッセージを構成するための設定という事になる。 そして、今回はデフォルトの動きとして、アプリケーション側がHTTPエラーを返した場合に、IIS はアプリケーションが設定した応答 (今回は json) を IIS のデフォルトのエラーメッセージで書き換えて応答を返したという事が起こっていた。これはデバッグ用のサーバーでは発生しない。

今回の設定内容

前提として今回は前回ポストの json レスポンスをちゃんと受け取れるようにしたいだけである。おそらく通常の本番環境では httpErrors や customErrors の情報が既にある可能性が高いため随時カスタマイズする必要があります。

existingResponse の設定を変える

説明としては

existingResponse 属性では、サーバーが HTTP エラー状態コードを返す場合に IIS 7.0 で既存の応答に対して何を行うかについて定義します。

及び

HTTP 状態コードがエラー、つまり応答コードが 400 以上の場合に、既存の応答をどうするかを指定します。

とあります。せっかくなので、設定内容も引用しておきます。

値: Auto 説明: SetStatus フラグが設定されている場合のみ、応答をそのままにしておきます。 数値は 0 です。

値: Replace 説明: SetStatus フラグが設定されている場合でも、既存の応答を置き換えます。 数値は 1 です。

値: PassThrough 説明: 既存の応答が存在する場合、応答をそのままにしておきます。 数値は 2 です。

とりあえず、書き換えられないようにするためには Auto (デフォルト) か PassThrough のいずれかに設定すれば良い事が分かります。 デフォルトは Auto なので、「SetStatus フラグ」なるものが設定されていないために、応答が書き換えられてしまうということも分かりました。

SetStatus フラグとは

HttpResponse.TrySkipIisCustomErrors プロパティ
http://msdn.microsoft.com/ja-jp/library/system.web.httpresponse.tryskipiiscustomerrors.aspx

Response.TrySkipIisCustomErrors

上述の通りで設定自体は割りと簡単にできる事が分かる。説明によると

TrySkipIisCustomErrors プロパティは、アプリケーションが IIS 7.0 でホストされる場合のみ使用されます。クラシック モードの IIS 7.0 で実行している場合、TrySkipIisCustomErrors プロパティの既定値は true です。統合モードで実行している場合、TrySkipIisCustomErrors プロパティの既定値は false です。

とありました。ちなみに私の PC で作ったサイトの設定は統合モードでしたのでこれも納得。

ちょっと古いけど利用サンプル

まとめ

httpErrors の設定をする事でとりあえずの対処はできる事が分かりました。Auto か PassThrough かは結局どっちがいいのかは私では判断できず。。少なくとも結局全てのケースで TrySkipIisCustomErrors を true にするぐらいなら PassThrough にすればいいような気がしますが、一方で保守的になると Auto にしたくなる気もします。この辺は勉強不足です。

参考