8

グローバルアクションフィルタを使用して、すべての例外を処理してログに記録しています。ExceptionContext.ExceptionHandledがtrueに変更されます。例外はどこで処理されますか?

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new ElmahHandleErrorAttribute()); 
     filters.Add(new HandleErrorAttribute()); 
    } 

これは世界的なアクションフィルタElmahHandleErrorAttributeが定義されている方法です - それはOnExceptionメソッドをオーバーライドします。

public class ElmahHandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext context) 
    { 
     //Is the exception handled already? context.ExceptionHandled seems to be true here 
     if (!context.IsChildAction && (context.HttpContext.IsCustomErrorEnabled)) 
     { 
      //Do other stuff stuff 
      //Log to Elmah    
     } 
    } 
    ... 
} 

OnExceptionメソッドが実行時にcontext.ExceptionHandledの値がtrueである理由を私は理解していません。 この例外はどのように処理されますか?

-EDIT- 私はWeb.ConfigcustomErrorsセクションを持っています。私はErrorControllerクラスを持っていて、GeneralHttp404というアクションがあります。

<customErrors mode ="On" defaultRedirect="Error/General"> 
     <error statusCode="404" redirect="Error/Http404"/> 
    </customErrors> 

私は理解していないことは、コントローラのアクションGeneralは(ブレークポイントがヒットされることはありません)が実行されていないが、ElmahHandleErrorAttributeOnException方法が実行を開始したときにExceptionContext.ExceptionHandledの値がtrueに設定されています。

+0

あなたのコードで 'context.ExceptionHandled'が表示されません。どこですか? – gdoron

+0

@gdoron context.ExceptionHandledのチェックを削除しました。'if(!context.IsChildAction &&!context.ExceptionHandled &&(context.HttpContext.IsCustomErrorEnabled))' – escist

+0

コントローラの 'OnException'メソッドをオーバーライドしましたか? – gdoron

答えて

19

例外が発生すると、グローバルフィルタの順序でin reverse orderが実行されます。つまり、最初にHandleErrorAttributeが実行されます。

あなたはHandleErrorAttributehereのコードを表示できますが、要するに、それ:

  1. のみExceptionHandledがfalseの場合は実行し、カスタムエラーが有効になっています。
  2. デフォルトではErrorと呼ばれるエラービューへのリダイレクトを設定します。
  3. ExceptionHandledをtrueに設定します。

それは第一のフィルタだとして、それが実行されると、その後、ExceptionHandledは、それがErrorにビューを設定することが原因とtrueにExceptionHandledを設定し、falseです。したがって、独自のフィルタを実行すると、ExceptionHandledが既にtrueに設定されているのです。カスタムエラーが無効になっている場合、HandleErrorAttributeはその処理を行っていないため、ExceptionHandledはまだfalseになります。この場合、ELMAHは処理されていない(死の黄色の画面)ため、とにかくエラーをログに記録するので、クラスのテストはエラーの重複ログを防止することです。 Generalアクションが実行されていないホエーについてのあなたの他の質問へのフィルターは、いくつかの明示が自分自身をリダイレクト設定しない場合

さて、defaultRedirectにのみ使用され、その例外はActionMethodと内部で発生するとき、それは実際には無視されますグローバルフィルタHandleErrorAttributeが登録されています。ただし、存在しないURL、つまりActionMethod内で発生しないエラーを入力した場合は呼び出されます。また、HandleErrorAttributeをGlobal.asax.csに登録する行をコメントアウトすると、コントローラの動作は常にGeneralになります。

+0

ありがとうございます。それは本当に私を助けました。 ElmahHandleErrorAttributeを実行する最初のフィルタにしたいと思います。このカスタムフィルタの順序を設定するとこれが解決されますか?このコメント(http://stackoverflow.com/a/9163926/1242061)によると、私は最初に実行したいフィルタに高いOrder値を与える必要があります。 – escist

+1

はい、Orderプロパティを使って遊んでいる可能性があります(ただし、グローバルフィルタではどうしたらよいかわかりませんが、属性として使用する場合にのみこれを行います)。 RegisterGlobalFiltersでフィルターを追加する順序を逆にするだけです...エラーが発生すると、最後に追加されたものが最初に実行されます。 なぜELMAHを最初に実行したいのかわかりませんが、実際に行った場合、ExceptionHandledをチェックすることはできません。その場合、常にfalseになるためです。 –

+0

フィルターの登録時に注文を指定しました。今私のカスタムフィルタ 'ElmahHandleErrorAttribute'がエラーを最初に処理しています。あなたの質問について、なぜELMAHが最初に走ってほしいのか分からない、あなたはこれが悪い考えだと思いますか?カスタムエラーページを表示し、エラータイプをチェックして特定のビューを表示したいので、これをやっています。 – escist

関連する問題