zoukankan      html  css  js  c++  java
  • MVC之 自定义过滤器(ActionFilterAttribute)

    一、自定义Filter

    自定义Filter需要继承ActionFilterAttribute抽象类,重写其中需要的方法,来看下ActionFilterAttribute类的方法签名。
     
    1.  
      //表示所有操作-筛选器特性的基类。
    2.  
      [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    3.  
      public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
    4.  
      {
    5.  
      protected ActionFilterAttribute();
    6.  
      // 在Action执行之后由 MVC 框架调用。
    7.  
      public virtual void OnActionExecuted(ActionExecutedContext filterContext);
    8.  
      // 在Action执行之前由 MVC 框架调用。
    9.  
      public virtual void OnActionExecuting(ActionExecutingContext filterContext);
    10.  
      // 在执行Result后由 MVC 框架调用。
    11.  
      public virtual void OnResultExecuted(ResultExecutedContext filterContext);
    12.  
      // 在执行Result之前由 MVC 框架调用。
    13.  
      public virtual void OnResultExecuting(ResultExecutingContext filterContext);
    14.  
      }


     
    因此自定义过滤器可以选择适当的方法来重写方可。下面来举个简单的例子:检查登录状态的过滤器,没有登录则跳转到登录页
    控制器代码
    1.  
      [CheckLogin]  //此处为自定义属性,要引用相应的命名空间
    2.  
      public ActionResult Index()
    3.  
      {
    4.  
      return View();
    5.  
      }
    6.  
       
    7.  
      public ActionResult Login()   //此Action自动往cookie里写入登录信息
    8.  
      {
    9.  
      HttpCookie hcUserName = new HttpCookie("username","admin");
    10.  
      HttpCookie hcPassWord = new HttpCookie("password","123456");
    11.  
      System.Web.HttpContext.Current.Response.SetCookie(hcUserName);
    12.  
      System.Web.HttpContext.Current.Response.SetCookie(hcPassWord);
    13.  
      return View();
    14.  
      }
    过滤器代码
    1.  
      public class CheckLogin : ActionFilterAttribute
    2.  
      {
    3.  
      //在Action执行之前 乱了点,其实只是判断Cookie用户名密码正不正确而已而已。
    4.  
      public override void OnActionExecuting(ActionExecutingContext filterContext)
    5.  
      {
    6.  
      HttpCookieCollection CookieCollect = System.Web.HttpContext.Current.Request.Cookies;if (CookieCollect["username"] == null || CookieCollect["password"] == null)
    7.  
      {
    8.  
      filterContext.Result = new RedirectResult("/Home/Login");
    9.  
      }
    10.  
      else
    11.  
      {
    12.  
      if (CookieCollect["username"].Value != "admin" && CookieCollect["password"].Value != "123456")
    13.  
      {
    14.  
      filterContext.Result = new RedirectResult("/Home/Login");
    15.  
      }
    16.  
      }
    17.  
      }
    18.  
      }//本示例贪图方便,将要跳转到的Action放在同一个Controller下了,如果将过滤器放到Controller类顶部,则永远也跳不到这个LoginAction。


     
    此过滤器实现的效果是,当用户Cookie中用户名和密码不正确则跳转到登录页,注意过滤器也可以放在整个Controller类的顶部,表示该Controller下的
    所有Action都执行该项检查。这样一来,控制器里的代码非常漂亮,再也不用所有的Action里都充斥着判断登录的代码了。
     
     

    二、带参数的自定义Filter

    首先,还是按照之前添加自定义过滤器的方法,添加一个自定义过滤器,只是里面多了一个属性,代码如下:
    1.  
      public class FilterAttribute : ActionFilterAttribute
    2.  
      {
    3.  
      public string Message { get; set; }
    4.  
       
    5.  
      public override void OnActionExecuting(ActionExecutingContext filterContext)
    6.  
      {
    7.  
      base.OnActionExecuting(filterContext);
    8.  
      filterContext.HttpContext.Response.Write("Action执行之前" + Message + "<br />");
    9.  
      }
    10.  
       
    11.  
      public override void OnActionExecuted(ActionExecutedContext filterContext)
    12.  
      {
    13.  
      base.OnActionExecuted(filterContext);
    14.  
      filterContext.HttpContext.Response.Write("Action执行之后" + Message + "<br />");
    15.  
      }
    16.  
       
    17.  
      public override void OnResultExecuting(ResultExecutingContext filterContext)
    18.  
      {
    19.  
      base.OnResultExecuting(filterContext);
    20.  
      filterContext.HttpContext.Response.Write("返回Result之前" + Message + "<br />");
    21.  
      }
    22.  
       
    23.  
      public override void OnResultExecuted(ResultExecutedContext filterContext)
    24.  
      {
    25.  
      base.OnResultExecuted(filterContext);
    26.  
      filterContext.HttpContext.Response.Write("返回Result之后" + Message + "<br />");
    27.  
      }
    28.  
      }


     
    然后在调用过滤器的时候,添加上该参数,Controller代码如下:
    1.  
      [Filter(Message="刘备")]  //参数给上
    2.  
      public ActionResult Index()
    3.  
      {
    4.  
      return View();
    5.  
      }


     
    输出结果如下:

    如果标签打到Controller上的话,TestFilterAttributeFilter将作用到Controller下的所有的Action。

      默认情况下Action上打了某个自定义标签后,虽然在Controller上也打上了此标签,但它只有Action上的标签起作用了。
      补充:如果Action没有打上该标签,那么Controller上的标签便会被执行。

       如果想让Action上的标签执行一次,然后Controller上的标签也执行一次,那么应该如何操作呢?

       我们只需在FilterAttribute类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]即可【下面类的最上面红色字体部分】,也就是让其成为可以多次执行的Action。代码如下:

    1.  
      [AttributeUsage(AttributeTargets.All,AllowMultiple = true)]
    2.  
      public class FilterAttribute : ActionFilterAttribute
    3.  
      {
    4.  
      public string Message { get; set; }
    5.  
      ......


    三、全局过滤器 

    有时我们想有些公共的方法需要每个Action都执行,但是又不想再每一个Controller上都打上Action标签,怎么办?幸好Asp。Net MVC3带来了一个美好的东西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的TestFilterAttribute 注册到全局Filter中。
    1.  
      public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    2.  
      {
    3.  
      filters.Add(new HandleErrorAttribute());
    4.  
      //注册全局过滤器
    5.  
      filters.Add(new TestFilterAttribute() { Message="全局"});
    6.  
      }
     
    这样就每个Action都会执行此过滤器,而不必每个Controller顶部都加上标签。
  • 相关阅读:
    豆瓣电台WP7客户端 MVVM重构记录之使用MVVM Light实现Event绑定
    使用DotNetOpenAuth来实现有道云笔记的授权
    豆瓣电台WP7客户端 MVVM重构记录之总结
    使用Npgsql连接Postgres
    WPF自定义一个MessageBox
    字符集其实很简单
    pytest封神之路第六步 断言技巧
    pytest封神之路第七步 用例查找原理
    一文搞懂Cookie,Session,Token,JWT
    典藏版Web功能测试用例库
  • 原文地址:https://www.cnblogs.com/shiyh/p/9469265.html
Copyright © 2011-2022 走看看