zoukankan      html  css  js  c++  java
  • asp.net mvc4 Controller与Action执行过程的研究(学习笔记)

    当IIS收到一个http请求,把请求信息发给对应的HttpModel(实际是实现类UrlRoutingModule),在HttpModel中会注册HttpApplication 类中的PostResolveRequestCache事件,通过此事件来动态选择映射HttpHandler处理程序。通过匹配到的RouteData类的RouteHandler属性得到IRouteHandler对象(MVC4MvcRouteHandlerasp.net原生的是PageRouteHandler),通过这个对象的GetHttpHandler方法就可以得到HttpHandler处理程序。具体代码如下:

    public virtual void PostResolveRequestCache(object sender, EventArgs e) {
       HttpApplication app = (HttpApplication)sender;
           HttpContextBase context = new HttpContextWrapper(app.Context);
           //详细见附1
           RouteData routeData = RouteCollection.GetRouteData(context);
           if (routeData == null) {
                return;
           }
           //详细见附1
           IRouteHandler routeHandler = routeData.RouteHandler;
           if (routeHandler is StopRoutingHandler) {
               return;
           }
           RequestContext requestContext = new RequestContext(context, routeData);
           context.Request.RequestContext = requestContext;
           IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); 
           if (httpHandler is UrlAuthFailureHandler) {
               if (FormsAuthenticationModule.FormsAuthRequired) {
                     UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
                return;
              }
              else {
               throw new HttpException(401, SR.GetString(SR.Assess_Denied_Description3));
              }
          }
          context.RemapHandler(httpHandler);//动态指定HttpHandler
     }
    

    1

    RouteCollection.GetHttpHandler方法获取匹配当前路由信息的RouteData,此方法是循环遍历RouteCollection集合并调用集合中RouteBase实现类为Route)的GetRouteData方法,并返回第一个不为NullRoudataRoudata实在RoudataBaseGetRouteData方法中被创建的,详见如下代码:

     

    public override RouteData GetRouteData(HttpContextBase httpContext) {
         string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
         RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults);
         if (values == null) {
              return null;
         }
    //为Roudata指定IRouteHandler对象
        RouteData routeData = new RouteData(this, RouteHandler);     
    if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) {
              return null;
         }
         foreach (var value in values) {
              routeData.Values.Add(value.Key, value.Value);
         }
         if (DataTokens != null) {
              foreach (var prop in DataTokens) {
                 routeData.DataTokens[prop.Key] = prop.Value;
              }
         }
        return routeData;
     }
    
    public class RouteData {
            private IRouteHandler _routeHandler; 
            public RouteData() {
            }
     
            public RouteData(RouteBase route, IRouteHandler routeHandler) {
                Route = route;
                RouteHandler = routeHandler;
            }
    //更多代码
    }
    

     

     MVC4:动态指定到HttpHandler后,就是处理Controller的创建和Action的执行了

    HttpHandler根据Routedata获取到Controller的名称,然后通过ControllerBuilder的静态方法GetControllerFactory获取IControllerFactory的实现类(默认是DefaultControllerFactory )来创建请求的IController的实现类的实例。最后执行IControllerExecute方法并传入请求上下文,方法Execute实现在System.Web.Mvc.ControllerBase这个抽象类中,Execute最终调用的是System.Web.Mvc.Controller中的ExecuteCore方法,ExecuteCore方法主要是保存TempData然后根据路由数据调用执行Action。代码如下:

     

    protected override void ExecuteCore()
    {
    PossiblyLoadTempData();
    try
    {
    string actionName = GetActionName(RouteData);
    //ActionInvoker是System.Web.Mvc.Controller的属性,该属性是一个返回类型为IActionInvoker的action执行器
    if (!ActionInvoker.InvokeAction(ControllerContext, actionName))
    {
    HandleUnknownAction(actionName);
    }
    }
    finally
    {
    PossiblySaveTempData();
    }
    }
    

     

    MVC4:执行Action的过程

    HttpHandler调用Controller.Execute方法后,最终将会通过IActionInvoke.ActionInvoker(ControllerContext controllerContext, string actionName)方法来执行ActionSystem.Web.Mvc.Controller类中有一个ActionInvoker属性,此属性提供IActionInvoke的实现类的实例,用来执行此Controller类中的Action,属性具体的赋值方式如下:

     

    protected virtual IActionInvoker CreateActionInvoker()
    {
    // Controller supports asynchronous operations by default.
    // Those factories can be customized in order to create an action invoker for each request.
    IAsyncActionInvokerFactory asyncActionInvokerFactory = Resolver.GetService<IAsyncActionInvokerFactory>();
    if (asyncActionInvokerFactory != null)
    {
    return asyncActionInvokerFactory.CreateInstance();
    }
    IActionInvokerFactory actionInvokerFactory = Resolver.GetService<IActionInvokerFactory>();
    if (actionInvokerFactory != null)
    {
    return actionInvokerFactory.CreateInstance();
    }
    // Note that getting a service from the current cache will return the same instance for every request.
    return Resolver.GetService<IAsyncActionInvoker>() ??
    Resolver.GetService<IActionInvoker>() ??
    new AsyncControllerActionInvoker();
    }
    

     

     ActionInvokerControllerDescriptor/ActionDescriptor的关系图如下:

    由此可以看出Controller选择IActionInvoker的机制是这样的:

    1、通过当前的DependencyResolverIAsyncActionInvokerFactory接口去获取注册的ActionInvoker工厂类,如果返回对象不为Null,则将其CreateInstance方法的返回值作为默认的ActionInvoker

    2、通过当前的DependencyResolverIActionInvokerFactory接口去获取注册的ActionInvoker工厂类,如果返回对象不为Null,则将其CreateInstance方法的返回值作为默认的ActionInvoker

    3、通过当前的DependencyResolverIAsyncActionInvoker接口去获取注册的ActionInvoker,如果返回对象不为Null,则将其作为默认的ActionInvoker

    4、通过当前的DependencyResolverIActionInvoker接口去获取注册的ActionInvoker,如果返回对象不为Null,则将其作为默认的ActionInvoker

    5、创建AsyncControllerActionInvoker对象作为默认的ActionInvoker

     

     

    获取到ActionInvoker后,就会执行InvokeAction方法(异步的是BeginInvokeAction/EndInvokeAction,方法中会根据controllerContext先获取ControllerDescriptor、然后根据controllerContextActionName通过ControllerDescriptor.FindAction方法获取ActionDescriptor(获取过程中需要通过Action选择器来过滤匹配Action,选择器包含ActionNameSelectorAttributeActionMethodSelectorAttribute,具体下面会有描述),获取到ActionDescriptor之后,开始执行Action的筛选器(IActionFilterIAuthorizationFilterIExceptionFilterIResultFilter),在通过ControllerDescriptor获取到ActionDescriptor之后,ActionInvoker会获取到所有的筛选器特性(FilterAttribute),按照四种类别存储在FilterInfo类的四个属性中(ActionFiltersAuthorizationFiltersExceptionFiltersResultFilters),然后开始循环验证AuthorizationFilters,(如果其中一个验证没有通过,就立即退出Action后续的执行,根据Result响应回复客户端),如果验证通过后,开始验证IActionFilter(这里看的比较饶人,因为要依次构建一个环环相扣的执行树,而这个树是从执行方向的尾部先构建的,所以为了保证执行顺序不反转就要先反转Filter,然后通过Aggregate方法循环Filte列表,再为每一个Filter建立lamda表达式层层组建为一个嵌套的Fun委托,最后再执行这个组建完成的委托,当其中某一个Filter验证失败的时候,就不再继续执行下一层的Fliter,直接返回Filter的验证失败Result),IActionFilter有两个方法,一个是开始执行Action前执行的方法OnActionExecuting,一个是执行完Action后执行的方法OnActionExecuted,验证不通过将不会执行OnActionExecuted方法。验证过所有的IActionFilter之后(Action也执行了并返回了Result)就开始验证IResultFilterIResultFilter也要分OnResultExecutingOnResultExecuted方法大致和IActionFilter差不多。

    执行三种筛选器和Action的时候有任何异常,都会被try/catch捕捉到,并开始执行IExceptionFilter筛选器,此筛选器和IAuthorizationFilter差不多。

    (需要研究的是ActionResult的执行过程)

    ControllerDescriptorActionDescriptor之间的关系

     

     

    ControllerDescriptorControllerDescriptor详解

     

     首先是抽象类型的ControllerDescriptor

     

     public abstract class ControllerDescriptor : ICustomAttributeProvider
       {  
            public virtual object[] GetCustomAttributes(bool inherit);
           public virtual object[] GetCustomAttributes(Type attributeType, bool inherit);
           public virtual bool IsDefined(Type attributeType, bool inherit);
            public virtual IEnumerable<FilterAttribute> GetFilterAttributes(bool useCache);
       	//获取指定Action,如果Action上应用了ActionNameSelectorAttribute特性(实现类
    	//ActionNameAttribute),则会根据特性的IsValidName方法的返回值来匹配
            public abstract ActionDescriptor FindAction(ControllerContext controllerContext, string actionName);
    	//返回此Controller中所有的Action描述类
    	//(仅限于公有实例方法,但是从.Controller中继承下来的方法除外)
            public abstract ActionDescriptor[] GetCanonicalActions();
       
          public virtual string ControllerName { get; }
          public abstract Type ControllerType { get; }
          public virtual string UniqueId { get; }
      }
      //此类用来获取Controller上的所有自定义特性或指定类型的特性
      public interface ICustomAttributeProvider
      {
          object[] GetCustomAttributes(bool inherit);
          object[] GetCustomAttributes(Type attributeType, bool inherit);
     //判断指定类型是否应用在Controller上
          bool IsDefined(Type attributeType, bool inherit);
      }
    

     

    ControllerDescriptor的默认实现类有两个,这两个都是通过反射的方式解析用于描述Controller的元数据:ReflectedControllerDescriptorReflectedAsyncControllerDescriptor,这两个类的区别就在FindActionGetCanonicalActions两个方法,主要区别在于ReflectedControllerDescriptor是通过反射匹配ActionNameReflectedAsyncControllerDescriptor要处理ActionName后面的{ActionName}Async{ActionName}Complete的后缀。

     

    抽象类型ActionDescriptorExecute方法要深入研究一下:

     

    public abstract class ActionDescriptor : ICustomAttributeProvider
       {
    	//这三个方法同ControllerDescriptor
           public virtual object[] GetCustomAttributes(bool inherit);
           public virtual object[] GetCustomAttributes(Type attributeType,  bool inherit);
           public virtual bool IsDefined(Type attributeType, bool inherit);
    
           public virtual IEnumerable<FilterAttribute> GetFilterAttributes( bool useCache);
          //Action需要接受的所有参数的描述
           public abstract ParameterDescriptor[] GetParameters();
    	//Action方法的执行
           public abstract object Execute(ControllerContext controllerContext,  IDictionary<string, object> parameters);
    

     

    //ActionSelector用于选择Action,可以自定义选择器(实现ActionMethodSelectorAttribute类)然后

    //以特性的方式应用在Action上,如Post Get请求分开的Action,就是通过选择器来实现的。值得注意的是,

    //Action的别名选择器特性ActionNameSelectorAttribute的匹配优先于

    //ActionMethodSelectorAttribute选择器,虽然优先,但是结果还是会被

    //ActionMethodSelectorAttribute选择器过滤

     

         public virtual ICollection<ActionSelector> GetSelectors();
    //Action筛选器,总共有四种筛选器IActionFilter、IAuthorizationFilter、IExceptionFilter
    //IResultFilter(需要继续深入研究)
          public virtual FilterInfo GetFilters();   
      
          public abstract string ActionName { get; }
          public abstract ControllerDescriptor ControllerDescriptor { get; }
          public virtual string UniqueId { get; }
      }
    

     

     抽象类ActionDescriptor的实现类:ReflectedActionDescriptor普通ActionReflectedAsyncActionDescriptorXxxAsync/XxxCompleted异步ActionTaskAsyncActionDescriptor是返回类型为TaskAction

     

     

     

     

     

     

  • 相关阅读:
    数组(Array)的使用方法
    Django中的事务操作
    什么是事务(Transaction)?事务的四个特性以及事务的隔离级别
    0.2 Django + Uwsgi + Nginx 的生产环境部署之实战篇
    0.1 Django + Uwsgi + Nginx 的生产环境部署之理论篇
    linux 进入编辑文件,保存退出相关命令
    Django--restframework
    使用用户名/邮箱/手机号 + 密码登陆 多形式登陆
    Django中异步任务---django-celery
    Redis 常用命令
  • 原文地址:https://www.cnblogs.com/lxiang/p/3966379.html
Copyright © 2011-2022 走看看