Fork me on GitHub

.net mvc 权限验证 Filter(过滤器)

一、知识了解

  1. Asp.Net MVC提供了以下几种默认的Filter:
  2. 大家注意一点,Asp.Net MVC提供的ActionFilterAttribute默认实现了IActionFilter和IResultFilter。而ActionFilterAttribute是一个Abstract的类型,所以不能直接使用,因为它不能实例化,所以我们想使用它必须继承一下它然后才能使用。

    Filter继承于ActionFilterAttribute抽象类,并可以覆写
    void OnActionExecuting(ActionExecutingContext)                                                                                                                                    
    voidOnActionExecuted(ActionExecutedContext)                                                                                                                                                
    void OnResultExecuting(ResultExecutingContext)                                                                                                                                                          
    void OnResultExecuted(ResultExecutedContext)。

  3. 它们的执行先后顺序如下:

  OnActionExecuting是Action执行前的操作

  OnActionExecuted则是Action执行后的操作

  OnResultExecuting是解析ActionResult前执行

  OnResultExecuted是解析ActionResult后执行

       接下来我们只要对以上的方法进行重写就可以在相应的步骤做一些操作了。
二、实操
       1.首先添加一个普通的类TestFilterAttribute,这个类要继承ActionFilterAttribute,代码如下

/// <summary>
 2     /// Filter 执行顺序Test,需要继承筛选器的基类ActionFilterAttribute
 3     /// </summary>
 4     public class TestFilterAttribute : ActionFilterAttribute
 5     {
 6         public string Message { get; set; }
 7 
 8         public override void OnActionExecuting(ActionExecutingContext filterContext)
 9         {
10             base.OnActionExecuting(filterContext);
11             filterContext.HttpContext.Response.Write("Action执行之前" + Message + "<br />");
12         }
13 
14         public override void OnActionExecuted(ActionExecutedContext filterContext)
15         {
16             base.OnActionExecuted(filterContext);
17             filterContext.HttpContext.Response.Write("Action执行之后" + Message + "<br />");
18         }
19 
20         public override void OnResultExecuting(ResultExecutingContext filterContext)
21         {
22             base.OnResultExecuting(filterContext);
23             filterContext.HttpContext.Response.Write("返回Result之前" + Message + "<br />");
24         }
25 
26         public override void OnResultExecuted(ResultExecutedContext filterContext)
27         {
28             base.OnResultExecuted(filterContext);
29             filterContext.HttpContext.Response.Write("返回Result之后" + Message + "<br />");
30         }
31     }

写完这个代码后,我们回到Action上,打上上面的标记如下所示:

 [TestFilterAttribute(Message = "Action")]
2         public ActionResult Index()
3         {
4             HttpContext.Response.Write("Action正在执行···<br />");
5             return Content("正在返回Result···<br />");
6         }

执行结果:

*如果我们将此标签打到Controller上的话,TestFilterAttributeFilter将作用到Controller下的所有的Action

*默认情况下Action上打了TestFilterAttribute 标签后,虽然在Controller上也打上了此标签,但它只有Action上的标签起作用了。

*补充:如果Action没有打上TestFilterAttribute标签,那么Controller上的标签便会被执行。

 

Index 执行时,Filter的方法只执行了一次,而某些情况下我们也想让Controller上的FilterAttribute也执行一次TestFilterAttribute,那我们怎么才能让Controller上的[TestFilter(Message = "controller")]也起作用呢?

答案是:我们只需在TestFilterAttribute类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]即可,也就是让其成为可以多次执行的Action。代码如下:

/// <summary>
    /// Filter 执行顺序Test,需要继承筛选器的基类ActionFilterAttribute
    /// </summary
    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] //打标记是让所有的Controller的标记生效
    public class TestFilterAttribute : ActionFilterAttribute
    {
        public string Message { get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            filterContext.HttpContext.Response.Write("Action执行之前" + Message + "<br />");
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            filterContext.HttpContext.Response.Write("Action执行之后" + Message + "<br />");
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            base.OnResultExecuting(filterContext);
            filterContext.HttpContext.Response.Write("返回Result之前" + Message + "<br />");
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            filterContext.HttpContext.Response.Write("返回Result之后" + Message + "<br />");
        }
    }

效果:

问:如何注册到全局?

答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的TestFilterAttribute 注册到全局Filter中

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            //注册全局过滤器
            filters.Add(new TestFilterAttribute() { Message="全局"});
        }

三、其他Fileter
1.AcceptVerbs      规定页面的访问形式,如

        [AcceptVerbs(HttpVerbs.Post)]
         public ActionResult Example(){
             return View();
         }

2.ActionName     如果不想用方法名做为Action名,或Action名为关键字的话,如

       [ActionName("class")]
         public ActionResult Example(){
             return View();
         }

3.NonAction     当前方法仅是普通方法不解析为Action

4.为Action添加缓存

        [OutputCache(Duration = 60, VaryByParam = "*")]
        public ActionResult Example()
        {
            return View();
        }

5.Action可以接受Html等危险代码(ASP.NET MVC在aspx中设置<%@ Page 的属性无法完成等同任务。)

        [ValidateInput(false)]
        public ActionResult Example()
        {
            return View();
        }

 

文章转载:https://www.cnblogs.com/zhangxiaoyong/p/6906288.html#autoid-0-0-0

posted @ 2022-01-04 09:11  WantRemake  阅读(398)  评论(0编辑  收藏  举报