zoukankan      html  css  js  c++  java
  • mvc源码解读(12)mvc四大过滤器之ActionFilter

        上一篇中我们随便聊了聊MVC的授权过滤器AuthorizeFilter,其实真正关于.net平台下的认证体系之复杂远远超出了我们的想像,对权限的控制我们只能找到相对安全的做法,并不能从绝对上杜绝不安全的验证,特别是对于.net下授权权限的控制。有机会我们可以回过头来深入的探讨有关.net平台下的权限控制体系。这一篇我们继续根据mvc3的源码来学习mvc的ActionFilter方法过滤器。

        和AuthorizeFilter原理一样,所有要用在Action方法上的方法过滤器特性都必须继承抽象类ActionFilterAttribute,该类是实现了不仅实现了接口FilterAttribute,还是实现了接口IActionFilter, IResultFilter,接口IActionFilter的成员如下:

     public interface IActionFilter {
            void OnActionExecuting(ActionExecutingContext filterContext);
            void OnActionExecuted(ActionExecutedContext filterContext);
        }

    OnActionExecuting在特性标注的方法执行之前执行的方法,同理OnActionExecuted是在特性标注的方法后执行的方法。接口IResultFilter我们等到下章来介绍。OnActionExecuting和OnActionExecuted接收ActionExecutingContext类实例作为参数,ActionExecutingContext类的成员如下:

    public virtual ActionDescriptor ActionDescriptor {get; set;}

     public virtual IDictionary<string, object> ActionParameters {get; set; }

      public ActionResult Result {get;set;}

    看到这些成员我们该笑了,ActionDescriptor属性我们前面已经介绍过了,通过这个属性我们可以获取执行的ActionName和ControllerDescriptor,进而得到Controller的一切信息。ActionParameters获取Action方法执行的参数。ActionExecutingContext类继承自类ControllerContext,该类有以下几个重要的成员如下:

            public virtual ControllerBase Controller {get; set; }

            public virtual HttpContextBase HttpContext {

                         get {if (_httpContext == null) {_httpContext = (_requestContext != null) ? _requestContext.HttpContext : new EmptyHttpContext(); }

                                    return _httpContext;}

                         set {_httpContext = value;}}

             public virtual RouteData RouteData {
                        get {
                            if (_routeData == null) {
                                    _routeData = (_requestContext != null) ? _requestContext.RouteData : new RouteData();
                              }
                        return _routeData;}
                        set {
                                _routeData = value;}
                             }

             public RequestContext RequestContext {

                        get {if (_requestContext == null) {

                                HttpContextBase httpContext = HttpContext ?? new EmptyHttpContext();                    

                                RouteData routeData = RouteData ?? new RouteData();

                               _requestContext = new RequestContext(httpContext, routeData);                

                         }                

                            return _requestContext;}            

                       set {_requestContext = value;}

    这里面我们需要注意的是HttpContext和RequestContext这两个属性。一个是封住了有关HTTP请求的信息,一个是封装了HttpContext和RouteData的请求上下文。看了那么多的微软定义的成员,我们来一个demo来演示ActionFilter的流程。

          1:新建一个mvc3的应用程序,并创建一个控制器:

     public class MyActionFilterController : Controller     {

                  [MyTestActionFiter]        

                 public ActionResult Index(){return View();}

                 public ActionResult TestIndex(){return View();}}

    两个Action对应的视图如下:

    @{Layout = null; }

    <!DOCTYPE html>

    <html> <head><title>Index</title></head><body><div><p>这里是测试的第一个页面--Index</p>    

    </div> </body> </html>

    @{Layout = null; }

    <!DOCTYPE html>

    <html> <head><title>TestIndex</title></head><body><div><p>这里是测试的第二个页面--TestIndex</p>    

    </div> /body></html>

    紧接着我们创建一个自定义的方法过滤器MyTestActionFiter,该类继承自ActionFilterAttribute,具体如下:

    public class MyTestActionFiter : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                //在动作请求之前执行的方法。
                filterContext.Result = new RedirectResult("/MyActionFilter/TestIndex");
                base.OnActionExecuting(filterContext);
            }
        }

    打开F12,我们请求的是如下所示:

     相应标头的信息如下:

     我们可以知道我们请求Index方法的时候,由于我们在OnActionExecuting方法中将请求重定向(HTTP状态码:302)到了TestIndex方法,由此可以证明OnActionExecuting是在Action方法之前执行。我们再来看一个demo。我们将MyTestActionFilter的方法改进一下:

    public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                //在动作请求之前执行的方法。
                //filterContext.Result = new RedirectResult("/MyActionFilter/TestIndex");
                filterContext.HttpContext.Response.Write("这是方法执行前的操作<br/>");
                base.OnActionExecuting(filterContext);
            }
           public override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                filterContext.HttpContext.Response.Write("这是方法执行之后的操作");
                base.OnActionExecuted(filterContext);
            }

    同时将MyActionFilter控制器改成如下:

     public class MyActionFilterController : Controller     {

              [MyTestActionFiter]        

                     public void Index() {Response.Write("这里是测试的第一个页面--Index<br/>"); }

                  }

    按F5运行,运行结果如下:

     

    看到这里,大家应该对ActionFiter的执行顺序应该有个大概的了解了吧:OnActionExecuting>Action>OnActionExecuted。但是有一点需要注意:ActionFiter都是在ViewResult执行之前执行,这也是为什么我在MyActionFilter中是直接输出内容,而不是返回ViewResult的原因,关于这一点,我们下一章结合ResultFilter做一个详细的解说。

  • 相关阅读:
    dpkg 被中断,您必须手工运行 sudo dpkg –configure -a 解决此问题
    运行wpscan报错Could not find 'nokogiri' (~> 1.8.0)
    理解:jar和war的区别
    AcWing3494. 国际象棋(状压DP)
    AcWing3422. 左孩子右兄弟(树形DP)
    python命名空间
    mysql日志大量报错“original commit timestamp is more recent than the immediate commit timestamp”
    python模块导入
    Centos-Docker镜像制作
    python面向对象之封装
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/2933269.html
Copyright © 2011-2022 走看看