mvc源码解读(14)-mvc四大过滤器之ExceptionFilter

这一章我们主要来讲异常过滤器ExceptionFilter,废话不多说,mvc3中默认的异常过滤器特性类是HandleErrorAttribute,该类的主要主要成员有:

public Type ExceptionType 
{
    getset
}
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<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;
        }
    }
}

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

<!DOCTYPE html>

<html> <head><title>ErrorView</title> </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; }

<!DOCTYPE html>

<html><head><title>Index</title> </head> <body><div>        

<p>这个是我自己try-Catch到的异常哦~~~</p></div></body></html>

运行结果如下:
这里写图片描述

我们可以看到,这一次他并没有执行OnException方法,异常直接被Catch住了。try-Catchmvc内置的异常处理器到底有什么样的关系?望可以得到解释~~

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页