• 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内置的异常处理器到底有什么样的关系?望可以得到解释~~

  • 相关阅读:
    心境的改变
    php之empty()函数常识性的错误
    php原生之实现图片,文件的下载
    多说,我还欠你一个会员
    开发模块化的初步理解
    Gradle模块化项目中使用了非模块化库的编译方法
    系统架构一一前端技术
    系统架构一一ORM的应用
    系统架构——依赖注入
    WPF下的RibbonApplicationMenu控件自定义
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/2936486.html
Copyright © 2020-2023  润新知