2012-08-07 152 views
62

我已經閱讀了StackOverflow上的十幾個類似的問題,但我似乎無法理解這一點。關於web.config和HandleErrorAttribute中的自定義錯誤節點,Error.cshtml是如何被調用的?最終,這個問題的答案可能是對ASP.NET MVC錯誤處理已經存在的幾個問題之一的回答。但事實是,我不知道哪一個。如何在ASP.NET MVC中調用Error.cshtml?

回答

82

裏面你的Global.asax您有以下方法:

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

此註冊HandleErrorAttribute作爲全球行動的過濾器。這意味着該處理程序會自動應用於所有控制器操作。現在,我們來看看如何通過查看源代碼來實現此屬性:

[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")] 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter { 

    private const string _defaultView = "Error"; 

    private readonly object _typeId = new object(); 

    private Type _exceptionType = typeof(Exception); 
    private string _master; 
    private string _view; 

    public Type ExceptionType { 
     get { 
      return _exceptionType; 
     } 
     set { 
      if (value == null) { 
       throw new ArgumentNullException("value"); 
      } 
      if (!typeof(Exception).IsAssignableFrom(value)) { 
       throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, 
        MvcResources.ExceptionViewAttribute_NonExceptionType, value.FullName)); 
      } 

      _exceptionType = value; 
     } 
    } 

    public string Master { 
     get { 
      return _master ?? String.Empty; 
     } 
     set { 
      _master = value; 
     } 
    } 

    public override object TypeId { 
     get { 
      return _typeId; 
     } 
    } 

    public string View { 
     get { 
      return (!String.IsNullOrEmpty(_view)) ? _view : _defaultView; 
     } 
     set { 
      _view = value; 
     } 
    } 

    public virtual void OnException(ExceptionContext filterContext) { 
     if (filterContext == null) { 
      throw new ArgumentNullException("filterContext"); 
     } 
     if (filterContext.IsChildAction) { 
      return; 
     } 

     // If custom errors are disabled, we need to let the normal ASP.NET exception handler 
     // execute so that the user can see useful debugging information. 
     if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { 
      return; 
     } 

     Exception exception = filterContext.Exception; 

     // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method), 
     // ignore it. 
     if (new HttpException(null, exception).GetHttpCode() != 500) { 
      return; 
     } 

     if (!ExceptionType.IsInstanceOfType(exception)) { 
      return; 
     } 

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

     // Certain versions of IIS will sometimes use their own error page when 
     // they detect a server error. Setting this property indicates that we 
     // want it to try to render ASP.NET MVC's error page instead. 
     filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
    } 
} 

源代碼包含註釋,不僅僅是自我解釋。它檢查的第一件事是您是否在您的web.config中啓用了自定義錯誤(即<customErrors mode="On">)。如果你沒有,它什麼都不做=> YSOD。如果您啓用了自定義錯誤,那麼它會呈現錯誤視圖,向它傳遞一個包含異常堆棧跟蹤和其他有用信息的模型。

+0

我對ASP.NET MVC還很新,但我認爲每個視圖都必須對應某個控制器的操作。這裏的控制器和操作是什麼?它如何知道去共享視圖?看起來這個機制在這裏是在錯誤視圖中中斷和交換的。 – LJM 2012-08-07 18:08:14

+2

是的,每個視圖必須對應一個控制器動作。在這種情況下,控制器動作是正在執行並引發異常的動作。可以是任何控制器操作。這個異常被全局動作過濾器攔截(在這種情況下是一個異常過濾器)並呈現錯誤視圖。由於異常在控制器動作內部被拋出,所以這個動作永遠不會返回,它只是在這個階段停止執行,並且將執行處理給錯誤處理器,後者又呈現視圖。 – 2012-08-07 19:05:29

+0

謝謝。這就是它。 – LJM 2012-08-07 19:24:24

相關問題