2012-01-24 34 views
5

Tôi đã bắt đầu một dự án mẫu MVC 3 trong VS10 và sửa đổi global.asax.cs như vậy:HandleErrorAttribute không làm việc

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new HandleErrorAttribute { ExceptionType = typeof(DivideByZeroException), View = "DivideByZeroException", Order = 1 }); 
    filters.Add(new HandleErrorAttribute { View = "AllOtherExceptions", Order = 2 }); 
} 

Để web.config Tôi nói thêm:

<customErrors mode="On"> 

Sau đó tạo ra lượt xem tương ứng và cuối cùng đã thêm DivideByZero-throw vào một trong các hành động.

Kết quả: Chế độ xem AllOtherExceptions được hiển thị.

Trả lời

21

Mặc dù tôi ghét không đồng ý với bất cứ điều gì Darin nói, anh ấy sai về điều này.

Không có vấn đề gì với việc đặt thuộc tính (đó là cách bạn đang giả định để làm điều đó).

Lý do duy nhất mã ban đầu của bạn không hoạt động như mong đợi là vì bạn đã đặt sai số Order.

Xem MSDN:

Các OnActionExecuting (ActionExecutingContext), OnResultExecuting (ResultExecutingContext), và OnAuthorization (AuthorizationContext) bộ lọc chạy theo thứ tự về phía trước. Các hành động OnActionExecuted (ActionExecutedContext), OnResultExecuting (ResultExecutingContext) và Bộ lọc OnException (ExceptionContext) chạy theo thứ tự ngược lại.

Vì vậy generic AllOtherExceptions bộ lọc của bạn cần phải được số thấp nhất Order, không phải là cao nhất.

Hy vọng điều đó sẽ hữu ích cho lần sau.

+0

Nghe có vẻ như bạn có một trường hợp, sợ hãi! Kể từ khi Darin đã giải quyết vấn đề của tôi, bạn sẽ phải chiến đấu với một với upvotes. – Martin

+0

Cảm ơn vì điều này - nên là câu trả lời! –

+0

Đã thay đổi câu trả lời ... – Martin

8

Bạn không nên đặt thuộc tính khi đăng ký bộ lọc hành động chung. Bạn có thể viết một bộ lọc lỗi tùy chỉnh xử lý:

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; 
      } 
     } 
    } 
} 

và sau đó đăng ký nó:

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

Nó hoạt động tất nhiên. Làm thế nào đến bạn không thể thiết lập các thuộc tính khi đăng ký một bộ lọc hành động toàn cầu? – Martin

0

Đừng kiểm tra câu trả lời sợ hãi của bên dưới. Nó chắc chắn đơn giản hơn, nếu nó hoạt động.

Kể từ khi nó đến sau một vài tuần, đây là cách bộ lọc của tôi cuối cùng đánh vần ra, sử dụng Darins phản ứng và kết hợp báo cáo Elmah, với mã số từ this chủ đề.

Tôi vẫn không biết tại sao bạn không thể đặt thuộc tính trên bộ lọc hành động chung.

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)); 
    } 
}