我在VS10中启动了一个MVC 3模板项目并修改了global.asax.cs:
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我添加了:
<customErrors mode="On">
然后创建了相应的视图,最后在其中一个动作中添加了DivideByZero-throw。
结果:呈现了AllOtherExceptions视图。
答案 0 :(得分:21)
虽然我讨厌不同意达林所说的任何事情,但他错了。
设置属性没有问题(这就是假设的方式)。
原始代码无法正常工作的唯一原因是因为您设置了Order
错误。
请参阅MSDN:
OnActionExecuting(ActionExecutingContext), OnResultExecuting(ResultExecutingContext),和 OnAuthorization(AuthorizationContext)过滤器以正向顺序运行。 OnActionExecuted(ActionExecutedContext), OnResultExecuting(ResultExecutingContext),和 OnException(ExceptionContext)过滤器以相反的顺序运行。
因此,您的通用AllOtherExceptions
过滤器必须是最低的Order
数字,而不是最高的数字。
希望下次有用。
答案 1 :(得分: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());
}
答案 2 :(得分: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));
}
}