.NET3.5を使用するasp.netWebフォームで次の設定を使用することで、この問題を回避することができました。
私が実装したパターンは、ヘッダーに正しいHTTPステータスコードを含むすべてのシナリオを処理するために独自に作成したため、web.configの.NETのカスタムリダイレクトソリューションをバイパスします。
まず、web.configのcustomErrorsセクションは次のようになります。
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
この設定により、CustomErrorsモードがonに設定され、後で必要になる設定になり、error.htmのdefaultRedirectにall-else-failsオプションが提供されます。これは、特定のエラーのハンドラーがない場合、またはデータベース接続の切断に沿って何かがある場合に役立ちます。
次に、グローバルasaxエラーイベントは次のとおりです。
protected void Application_Error(object sender, EventArgs e)
{
HandleError();
}
private void HandleError()
{
var exception = Server.GetLastError();
if (exception == null) return;
var baseException = exception.GetBaseException();
bool errorHandled = _applicationErrorHandler.HandleError(baseException);
if (!errorHandled) return;
var lastError = Server.GetLastError();
if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
Server.ClearError();
}
}
このコードは、エラーを処理する責任を別のクラスに移しています。エラーが処理されず、CustomErrorsがオンになっている場合は、本番環境にあり、何らかの理由でエラーが処理されていない場合があります。ユーザーに表示されないようにするためにここでクリアしますが、何が起こっているのかがわかるようにElmahにログインします。
applicationErrorHandlerクラスは次のようになります。
public bool HandleError(Exception exception)
{
if (exception == null) return false;
var baseException = exception.GetBaseException();
Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);
if (!HttpContext.Current.IsCustomErrorEnabled) return false;
try
{
var behavior = _responseBehaviorFactory.GetBehavior(exception);
if (behavior != null)
{
behavior.ExecuteRedirect();
return true;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return false;
}
このクラスは基本的にコマンドパターンを使用して、発行されたエラーのタイプに適したエラーハンドラーを見つけます。ほとんどすべてのエラーは上位レベルの例外にラップされるため、このレベルでException.GetBaseException()を使用することが重要です。たとえば、aspxページから「thrownew System.Exception()」を実行すると、System.Exceptionではなく、このレベルでHttpUnhandledExceptionが受信されます。
「ファクトリ」コードは単純で、次のようになります。
public ResponseBehaviorFactory()
{
_behaviors = new Dictionary<Type, Func<IResponseBehavior>>
{
{typeof(StoreException), () => new Found302StoreResponseBehavior()},
{typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
{typeof(HttpException), () => new HttpExceptionResponseBehavior()},
{typeof(Exception), () => new Found302DefaultResponseBehavior()}
};
}
public IResponseBehavior GetBehavior(Exception exception)
{
if (exception == null) throw new ArgumentNullException("exception");
Func<IResponseBehavior> behavior;
bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);
if (!tryGetValue)
_behaviors.TryGetValue(typeof(Exception), out behavior);
if (behavior == null)
Elmah.ErrorSignal.FromCurrentContext().Raise(
new Exception(
"Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
exception));
return behavior();
}
結局、私は拡張可能なエラー処理スキームのセットアップを手に入れました。定義されている「動作」のそれぞれに、エラーのタイプのカスタム実装があります。たとえば、Http例外はステータスコードが検査され、適切に処理されます。404ステータスコードには、ヘッダーに記述された適切なステータスコードとともに、Request.RedirectではなくServer.Transferが必要です。
お役に立てれば。