2012-01-24 15 views
5

私はVS10でMVC 3のテンプレートプロジェクトを開始し、変更したglobal.asax.csを働いていない HandleErrorAttributeなど

<customErrors mode="On"> 

が次に作成対応するビューを作成し、最後にDivideByZero-throwをアクションの1つに追加しました。

結果:ビューAllOtherExceptionsがレンダリングされます。

答えて

21

私はダーリンの言うことに同意できませんが、彼は間違っています。

プロパティを設定することに問題はありません(とすると、となります)。

元のコードが期待通りに機能しなかった唯一の理由は、Orderが正しく設定されていないためです。

MSDNを参照してください:

OnActionExecuting(ActionExecutingContext)、 OnResultExecuting(ResultExecutingContext)、および OnAuthorization(AuthorizationContext)は前方の順序で実行されるフィルタ。 OnActionExecuted(ActionExecutedContext)、 OnResultExecuting(ResultExecutingContext)、および OnException(ExceptionContext)フィルタは、逆の順序で実行されます。

一般的なAllOtherExceptionsフィルタは、最も低い数値のOrderである必要があります。

うまくいけば、次回も役立ちます。

+0

あなたは恐怖を持っているように聞こえます!ダーリンは私の問題を解決して以来、あなたはアップフォートでこれを戦わなければならないでしょう。 – Martin

+0

ありがとうございます - 答えになるはずです! –

+0

答えが変更されました... – Martin

8

グローバルアクションフィルタを登録するときは、プロパティを設定しないでください。

public class MyHandleErrorAttribute : FilterAttribute, IExceptionFilter 
{ 
    public void OnException(ExceptionContext filterContext) 
    { 
     if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled)) 
     { 
      Exception innerException = filterContext.Exception; 
      if ((new HttpException(null, innerException).GetHttpCode() == 500)) 
      { 
       var viewName = "AllOtherExceptions"; 
       if (typeof(DivideByZeroException).IsInstanceOfType(innerException)) 
       { 
        viewName = "DivideByZeroException"; 
       } 

       string controllerName = (string)filterContext.RouteData.Values["controller"]; 
       string actionName = (string)filterContext.RouteData.Values["action"]; 
       HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); 
       ViewResult result = new ViewResult 
       { 
        ViewName = viewName, 
        ViewData = new ViewDataDictionary<HandleErrorInfo>(model), 
        TempData = filterContext.Controller.TempData 
       }; 
       filterContext.Result = result; 
       filterContext.ExceptionHandled = true; 
       filterContext.HttpContext.Response.Clear(); 
       filterContext.HttpContext.Response.StatusCode = 500; 
       filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
      } 
     } 
    } 
} 

し、それを登録します:カスタムハンドル誤差フィルタを書くことができ

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new MyHandleErrorAttribute()); 
} 
+3

それはもちろん働いた。グローバルアクションフィルタを登録するときにどのようにプロパティを設定できないのですか? – Martin

0

下記の恐怖の答えをチェックしてください。それが動作すれば確かに簡単です。

数週間後に来て以来、私のフィルタはDarinsレスポンスを使用し、Elmahのレポート機能を組み込んで、thisというトピックのコードで最終的に綴られています。

グローバルアクションフィルタでプロパティを設定できない理由はまだ分かりません。

public class MyHandleErrorAttribute : FilterAttribute, IExceptionFilter 
{ 
    public void OnException(ExceptionContext filterContext) 
    { 
     if (!filterContext.IsChildAction && 
      (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled)) 
     { 
      var innerException = filterContext.Exception; 
      if ((new HttpException(null, innerException).GetHttpCode() == 500)) 
      { 
       var viewName = "GeneralError"; 
       if (typeof (HttpAntiForgeryException).IsInstanceOfType(innerException)) 
        viewName = "SecurityError"; 

       var controllerName = (string) filterContext.RouteData.Values["controller"]; 
       var actionName = (string) filterContext.RouteData.Values["action"]; 
       var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); 
       var result = new ViewResult 
             { 
              ViewName = viewName, 
              ViewData = new ViewDataDictionary<HandleErrorInfo>(model), 
              TempData = filterContext.Controller.TempData 
             }; 

       filterContext.Result = result; 
       filterContext.ExceptionHandled = true; 
       filterContext.HttpContext.Response.Clear(); 
       filterContext.HttpContext.Response.StatusCode = 500; 
       filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 

//From here on down, this is all code for Elmah-reporting. 
       var version = Assembly.GetExecutingAssembly().GetName().Version; 
       filterContext.Controller.ViewData["Version"] = version.ToString(); 

       var e = filterContext.Exception; 
       if (!filterContext.ExceptionHandled // if unhandled, will be logged anyhow 
        || RaiseErrorSignal(e) // prefer signaling, if possible 
        || IsFiltered(filterContext)) // filtered? 
        return; 

       LogException(e); 
      } 
     } 
    } 

    private static bool RaiseErrorSignal(Exception e) 
    { 
     HttpContext context = HttpContext.Current; 
     if (context == null) 
      return false; 
     var signal = ErrorSignal.FromContext(context); 
     if (signal == null) 
      return false; 
     signal.Raise(e, context); 
     return true; 
    } 

    private static bool IsFiltered(ExceptionContext context) 
    { 
     var config = context.HttpContext.GetSection("elmah/errorFilter") 
        as ErrorFilterConfiguration; 

     if (config == null) 
      return false; 

     var testContext = new ErrorFilterModule.AssertionHelperContext(
      context.Exception, HttpContext.Current); 

     return config.Assertion.Test(testContext); 
    } 

    private static void LogException(Exception e) 
    { 
     HttpContext context = HttpContext.Current; 
     ErrorLog.GetDefault(context).Log(new Error(e, context)); 
    } 
}