• MVC 过滤器


      在mvc中,过滤器是无此不在,可能没有显示的去调用,所以很多人还不是很理解,本节就通过几个例子来说明一下mvc中过滤器的使用。

    一、过滤器概况

      为什么说过滤器在mvc中无此不在呢?默认添加一个的控制器,会发现其继承的是Controller类,在Controller上面按F12转到定义:

    public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter

     其中上面的几个接口,带有Filter后缀名的,也就是我们本节要说明的过滤器了,共四个:ActionFilter(方法过滤器),ResultFilter(结果过滤器,感觉不是很好听,就这样叫吧),AuthorizationFilter(授权过滤器),ExceptionFilter(异常处理过滤器)。现在应该知道无处不在的原因了吧,难道说你不是用Controller。好了废话不多扯了,开始进入我们的正题。

    二、过滤器说明

    2.1 IActionFilter有两个方法:

            // 摘要:
            //     Called after the action method executes.
            //
            // 参数:
            //   filterContext:
            //     The filter context.
            void OnActionExecuted(ActionExecutedContext filterContext);
            //
            // 摘要:
            //     Called before an action method executes.
            //
            // 参数:
            //   filterContext:
            //     The filter context.
            void OnActionExecuting(ActionExecutingContext filterContext);
    View Code

    一个是在调用前使用,一个是在调用后使用的。
    2.2同样IResultFilter也有两个方法:

            // 摘要:
            //     Called after an action result executes.
            //
            // 参数:
            //   filterContext:
            //     The filter context.
            void OnResultExecuted(ResultExecutedContext filterContext);
            //
            // 摘要:
            //     Called before an action result executes.
            //
            // 参数:
            //   filterContext:
            //     The filter context.
            void OnResultExecuting(ResultExecutingContext filterContext);
    View Code

    2.3 IAuthorizationFilter:

    void OnAuthorization(AuthorizationContext filterContext);

    这个是在所有过滤器调用之前调用的方法。
    2.4 IExceptionFilter

    void OnException(ExceptionContext filterContext);

    这个是在异常发生时调用。

    感觉讲的还是不够清楚,使用书中的一个表格来说明:(虽然是e文,感觉不是很难看懂)

    好了,简单的也说明了一些上面的方法,可能还是不清楚怎么去使用这些过滤器。接下来我将会先比较一下他们的相同点,然后去举几个例子来说明其用途。

    三、过滤器的使用

    3.1共同点

    现在我们回头来看上面几个接口的方法,主要是看其形参——一个共同的特点是其包括一个基类为ControllerContext的形参。这个参数有很多有用的属性,如HttpContextBase,ControllerBase,RouteData等这些属性都直接关系着我们http请求以及请求的去向。

    3.2实例

    接下来就来看几个实例,感受一下过滤器的厉害:如果例子中有不足的地方,或者有更好的使用,请大牛指点。

    例子1.让含有admin的controller必须要登陆,否则转到登陆界面。

        public class AdminActionFilter:Controller
        {
            
            protected override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                //当controller里面含有admin并且session为空时,转到登陆页
                if (filterContext.RouteData.Values["controller"].ToString().ToLower().Contains("admin")
                    && filterContext.HttpContext.Session.Count==0)
                {
                    filterContext.Result = RedirectToAction("LogOn", "Account");//Account/LogOn
                    return;
                }
            }
        }

    然后让admin文件夹里面的controller去实现继承我们定义的AdminActionFilter.

    例子2.统计异常(该实例基于HandleErrorAttribute)

    public class CustomExceptionFilter : HandleErrorAttribute
        {
            public override void OnException(ExceptionContext filterContext)
            {
                //如果异常未处理
                if (!filterContext.ExceptionHandled)
                {
                    Exception innerException = filterContext.Exception;
                    //如果错误码为500
                    if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
                    {
                        //获取出现异常的controller名和action名,用于记录
                        string controllerName = (string)filterContext.RouteData.Values["controller"];
                        string actionName = (string)filterContext.RouteData.Values["action"];
                        //定义一个HandErrorInfo,用于Error页使用
                        HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
                       //ViewResult是ActionResult,经常出现在controller中action方法return后面,但是出现形式是View()
                        ViewResult result = new ViewResult
                        {
                            ViewName = this.View,
                            MasterName = this.Master,
                            //定义ViewData,使用的是泛型
                            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;
                    }
                }
                base.OnException(filterContext);
            }
        }

    然后前台的error.cshtml应该更改为

    @model System.Web.Mvc.HandleErrorInfo
    
    @{
        ViewBag.Title = "错误";
    }
        <p> 
            错误类型: <b>@Model.Exception.GetType().Name</b> 
            控制器和方法名称 <b>@Model.ControllerName</b>'s <b>@Model.ActionName</b>  
        </p> 
        <p> 
            异常信息 <b><@Model.Exception.Message></b> 
        </p> 
    @***********************************************************
    这部分可以用来测试用
    *************************************************************   
     <p>堆栈信息:</p> 
        <pre>@Model.Exception.StackTrace</pre>
            <p> 
                There was a <b>@Model.Exception.GetType().Name</b> 
                while rendering <b>@Model.ControllerName</b>'s 
                <b>@Model.ActionName</b> action. 
            </p> 
        <p> 
            The exception message is: <b><@Model.Exception.Message></b> 
        </p> 
        <p>Stack trace:</p> *@
    @*    <pre>@Model.Exception.StackTrace</pre>*@
    View Code
    之后web.config里面 由于我们的view中的error页面可能会出现异常,所以为了防止这样的问题发生, <system.web/>节点里面可以配置一下,<customErrors mode="On" defaultRedirect="ErrorPage.htm">
    使用global文件注册过滤器。
    如果没有使用global注册的话,只能一个个去实现,所以我们最好使用哦global去实现注册。
      public static void RegisterGlobalFilters(GlobalFilterCollection filters)       
     {            //filters.Add(new HandleErrorAttribute());       
          filters.Add(new CustomExceptionFilter());   
     }
    下面我把异常处理的源码上传上去,仅供参考。
    源码
    
    
    
    
    
  • 相关阅读:
    领域驱动设计(Domain Driven Design)
    程序员的梦想:意图编程
    怎样才算是好的软件可维护性设计?
    微软的patternshare.org初步体验
    转:JDepend:管理代码依赖性
    MAB, 专用的amazon浏览器,有点意思!
    宾夕法尼亚大学沃顿商学院:沃顿知识在线
    我的笔记本的鼠标又乱跑了!寻求帮助!
    能否让博客园对Firefox支持得好一些!
    交互设计:《About Face 2.0》中译本精彩节选
  • 原文地址:https://www.cnblogs.com/lzhp/p/3076478.html
Copyright © 2020-2023  润新知