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

    这一章我们主要来讲异常过滤器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<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();
        }

对应的inde的View如下:

@{     Layout = null; }

<!DOCTYPE html>

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

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

运行结果如下:

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

posted @ 2013-02-28 11:49  肖&申&克  阅读(480)  评论(0编辑  收藏  举报