62
我已經閱讀了StackOverflow上的十幾個類似的問題,但我似乎無法理解這一點。關於web.config和HandleErrorAttribute中的自定義錯誤節點,Error.cshtml是如何被調用的?最終,這個問題的答案可能是對ASP.NET MVC錯誤處理已經存在的幾個問題之一的回答。但事實是,我不知道哪一個。如何在ASP.NET MVC中調用Error.cshtml?
我已經閱讀了StackOverflow上的十幾個類似的問題,但我似乎無法理解這一點。關於web.config和HandleErrorAttribute中的自定義錯誤節點,Error.cshtml是如何被調用的?最終,這個問題的答案可能是對ASP.NET MVC錯誤處理已經存在的幾個問題之一的回答。但事實是,我不知道哪一個。如何在ASP.NET MVC中調用Error.cshtml?
裏面你的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。如果您啓用了自定義錯誤,那麼它會呈現錯誤視圖,向它傳遞一個包含異常堆棧跟蹤和其他有用信息的模型。
我對ASP.NET MVC還很新,但我認爲每個視圖都必須對應某個控制器的操作。這裏的控制器和操作是什麼?它如何知道去共享視圖?看起來這個機制在這裏是在錯誤視圖中中斷和交換的。 – LJM 2012-08-07 18:08:14
是的,每個視圖必須對應一個控制器動作。在這種情況下,控制器動作是正在執行並引發異常的動作。可以是任何控制器操作。這個異常被全局動作過濾器攔截(在這種情況下是一個異常過濾器)並呈現錯誤視圖。由於異常在控制器動作內部被拋出,所以這個動作永遠不會返回,它只是在這個階段停止執行,並且將執行處理給錯誤處理器,後者又呈現視圖。 – 2012-08-07 19:05:29
謝謝。這就是它。 – LJM 2012-08-07 19:24:24