这一章我们主要来讲异常过滤器ExceptionFilter
,废话不多说,mvc3
中默认的异常过滤器特性类是HandleErrorAttribute
,该类的主要主要成员有:
public Type ExceptionType
{
get;set
}
public string View
{
get
{
if (string.IsNullOrEmpty(this._view))
{
return "Error";
}
return this._view;
}
set
{
this._view = value;
}
}
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
{
Exception innerException = filterContext.Exception;
if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
{
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 = this.View,
MasterName = this.Master,
ViewData = new ViewDataDictionary(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;
}
}
}
其中ExceptionType
表示异常的类型,默认是所有异常的基类Exception
,表示会处理所有的标准异常。View
属性表示抛出异常时该显示什么样的视图给用户,如果每没有自定义的View
,系统默认输出的是字符串“Error
”,OnException
方法用于系统出现异常时调用的方法,我们看红色代码这两句:
filterContext.ExceptionHandled = true;
new HttpException(null, innerException).GetHttpCode() == 500
ExceptionHandled
属性是布尔值,表示该抛出的异常是否被处理了,true
表示已经被处理,false
表示没有被处理,如果被处理过的异常,一定要将ExceptionHandled
设置为true
,防止父类或者更高级别的异常处理重复的处理改异常。而HttpCode=500表示会优先调用MVC
框架自己的处理异常,然后将ExceptionHandled
设置为true
。我们先来看一段demo:
我们自定义一个异常类过滤器MyExceptionFilter
,继承自HandleErrorAttribute
并重写了OnException
方法,实现方法如下:
public class MyExceptionFilter : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled && filterContext.Exception is DivideByZeroException)
{
filterContext.Result = new RedirectResult("/MyException/ErrorView");
filterContext.ExceptionHandled = true;
}
base.OnException(filterContext);
}
}
我们创建一个MVC3
的项目,创建一个MyException
控制器,具体代码如下:
[MyExceptionFilter]
public ActionResult Index()
{
int firstNumber = 10;
int secondNumber = 0;
int c = firstNumber / secondNumber;
return View();
}
public ActionResult ErrorView()
{
return View();
}
ErrorView
具体代码如下:
@{ Layout = null; }
<html> <head><title>ErrorViewtitle> head> <body><div>
<p>这是一个异常页面哦~~~~~p>
div> body> html>
我们可以看到,在Index
中出现异常的时候,执行了OnException
方法,并将用户的请求转到了我们自定义的错误页面,同时标记改异常已经处理过了,如果上文我们说到过,若是每个Controller
都要贴上这个异常标签,会很麻烦,因此我们可以在全局文件文件注册一个全局的异常过滤器,具体如下:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
//filters.Add(new MyTestResultFiter() { FilterMessage="标志全局过滤器"});
filters.Add(new MyExceptionFilter());
//全局的异常过滤器
}
,同时在配置文件中设置i如下:
<system.web>
<customErrors mode="On">customErrors>
system.web>
这是一种情况,我们来看另外一种情况,我们自己在try-catch
中处理该异常,会有什么结果呢,我们将Index
里面的方法稍作修改如下:
[MyExceptionFilter]
public ActionResult Index()
{
try
{
int firstNumber = 10;
int secondNumber = 0;
int c = firstNumber / secondNumber;
}
catch (DivideByZeroException ex)
{
HttpContext.Response.Write(ex.Message.ToString());
}
return View();
}
对应的index的View
如下:
@{ Layout = null; }
<html><head><title>Indextitle> head> <body><div>
<p>这个是我自己try-Catch到的异常哦~~~p>div>body>html>
我们可以看到,这一次他并没有执行OnException
方法,异常直接被Catch
住了。try-Catch
和mvc
内置的异常处理器到底有什么样的关系?望可以得到解释~~