zoukankan      html  css  js  c++  java
  • 004. Asp.Net Routing与MVC 之二: 请求如何激活Controller和Action

    上篇讲到 请求到达 MvcRouteHandler ,并且透过 IRouteHandler.GetHttpHandler 获取到了真正的处理程序 MvcHandler

    这次我们看看,MvcHandler是如何依据请求,来激活对应的controller和Action来处理请求的。

    一、先看看MvcHandler 的核心内容

       1: public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
       2: {
       3:     protected virtual void ProcessRequest(HttpContext httpContext)
       4:     {
       5:         //使用HttpContextWrapper对HttpContext进行封装,封装的目的是为了解耦以获得可测试性.然后从RequestContext.RouteData中提取Controller名称.
       6:         HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
       7:         this.ProcessRequest(httpContext2);
       8:     }
       9:     
      10:     protected internal virtual void ProcessRequest(HttpContextBase httpContext)
      11:     {
      12:         IController controller;
      13:         IControllerFactory controllerFactory;
      14:         this.ProcessRequestInit(httpContext, out controller, out controllerFactory);//获取到Controler和ControllerFactory实例,并赋值给局部变量
      15:         try
      16:         {
      17:           //Action的调用,下一篇介绍
      18:                 //当前Controler对象的Action的创建与执行(执行包括:加载TempData, 创建及执行Action,处理Action返回的ActionResult ,保存TempData数据)
      19:                 controller.Execute(this.RequestContext);
      20:                 
      21:         }
      22:         finally
      23:         {
      24:             //释放当前Controler对象
      25:             controllerFactory.ReleaseController(controller); 
      26:         }
      27:     }
      28: }

     

    二、Controller的激活

    从上述代码中可以看出,对Controller激活的相关的操作是通过MvcHandler类的 ProcessRequestInit 方法来执行,而执行完成后,将获取到Controller和ControllerFactory实例。

    this.ProcessRequestInit(httpContext, out controller, out controllerFactory) ,下面就通过这个方法的内部代码来剖析下Controller的激活的机制

       1: private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
       2: {
       3:  
       4:             // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
       5:             // at Request.Form) to work correctly without triggering full validation.
       6:             // Tolerate null HttpContext for testing.
       7:             //看不明白
       8:             HttpContext currentContext = HttpContext.Current;
       9:             if (currentContext != null)
      10:             {
      11:                 bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);
      12:                 if (isRequestValidationEnabled == true)
      13:                 {
      14:                     ValidationUtility.EnableDynamicValidation(currentContext);
      15:                 }
      16:             }
      17:             //为响应添加特定的头标示:MvcVersionHeaderName, MvcVersion
      18:             AddVersionHeader(httpContext);
      19:             //从当前请求的路由集合中,移除可选的路由参数
      20:             RemoveOptionalRoutingParameters();
      21:  
      22:             // Get the controller type
      23:             //从当前请求的路由集合中,检索名为"controller"参数的值
      24:             string controllerName = RequestContext.RouteData.GetRequiredString("controller");
      25:  
      26:             // Instantiate the controller and call Execute
      27:             //通过 ControllerBuilder 获取 当前的 controllFactory 控制器工厂
      28:             factory = ControllerBuilder.GetControllerFactory();
      29:             //通过controllFactory 控制器工厂 ,以及前边获取到的 controllerName,构建一个 controller类型实例。
      30:             controller = factory.CreateController(RequestContext, controllerName);
      31:             if (controller == null)
      32:             {
      33:                 throw new InvalidOperationException(
      34:                     String.Format(
      35:                         CultureInfo.CurrentCulture,
      36:                         MvcResources.ControllerBuilder_FactoryReturnedNull,
      37:                         factory.GetType(),
      38:                         controllerName));
      39:             }
      40: }
      41:  

     

    由于使用了out关键字,这个方法中的执行过程中所得到的值,即:赋值给ProcessRequest方法中声明的Controller和ControllerFactory

     

     

    MVCHander –>  ProcessRequest()

    xxxxxControllerControllerFactory

     

    IController.Excute();

    ControllerBase.Excute().ExcuteCore()

    Controller.ExecuteCore()  { . GetActionName  ;  IActionInvoker.InvokeAction() }

    IActionInvoker.InvokeAction() {

    get methodInfo  //sys

    处理参数  // BindModel

    methodInfo.invoke();//sys

    }

     

    1.定义Model

    2.Model 里注册事件 ,附加 routerHander

    3。routerHander 里 返回真正的  hander

    4. hander.ProcessRequest(  HttpCotent content )

    {

    get Controller type

    get Action(Method)  methodinfo

     

    var invokeResult = method.Invoke(controllerContext.Controller, parameters.ToArray())
                //as ActionResult;

            controllerContext.RequestContext.HttpContext.Response.Write(invokeResult);

     

     

    }

     

    一、mvc 下 url 的各种玩法

    ip/home/index/3

    ip/3

    二、

    //    parameters.Add(this.ModelBinder.BindModel(controllerContext, parameter.Name, parameter.ParameterType));

     

     

    以下是没有搞清楚的内容,如何获取工厂,工厂又如何依据名字,创建一个controller类型实例。

     

    显然,上述的代码中有两行重要代码:

    1、factory = this.ControllerBuilder.GetControllerFactory();

        this.ControllerBuilder是MvcHandler类的一个属性,属性返回的是MvcHandler类声明的一个 ControllerBuilder类型的字段,属性在返回时会判断当前字段是否为空,如果为空,则调用ControllerBuilder类的静态属性 Current字段,来获取一个ControllerBuilder实例。

    接下来再看一下ControllerBuilder类
       1: namespace System.Web.Mvc
       2: {
       3:     public class ControllerBuilder
       4:     {
       5:         //声明静态字段,执行此类的构造函数
       6:         private static ControllerBuilder _instance = new ControllerBuilder();
       7:  
       8:         private Func<IControllerFactory> _factoryThunk = () => null;
       9:         private HashSet<string> _namespaces = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
      10:  
      11:         //暂且理解为是封装ControllerFactory的一个类,通过该类的Current属性来获取当前封装的ControllerFactory实例
      12:         private IResolver<IControllerFactory> _serviceResolver;
      13:  
      14:         public ControllerBuilder()
      15:             : this(null) //: this(null)表示执行带一个参数的构造函数,并且传入的参数为Null
      16:         {
      17:         }
      18:  
      19:         internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
      20:         {
      21:             //如果传入的参数为null,则实例化一个SingleServiceResolver类并赋值给私有字段_serviceResolver。
      22:             _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
      23:                                                       () => _factoryThunk(),
      24:                                                       new DefaultControllerFactory { ControllerBuilder = this },
      25:                                                       "ControllerBuilder.GetControllerFactory");
      26:         }
      27:  
      28:         public static ControllerBuilder Current
      29:         {
      30:             //获取Controller实例
      31:             get { return _instance; }
      32:         }
      33:  
      34:         public HashSet<string> DefaultNamespaces
      35:         {
      36:             get { return _namespaces; }
      37:         }
      38:  
      39:         [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Calling method multiple times might return different objects.")]
      40:         public IControllerFactory GetControllerFactory()
      41:         {
      42:             //获取ControllerFactory实例
      43:             return _serviceResolver.Current;
      44:         }
      45:  
      46:         public void SetControllerFactory(IControllerFactory controllerFactory)
      47:         {
      48:             if (controllerFactory == null)
      49:             {
      50:                 throw new ArgumentNullException("controllerFactory");
      51:             }
      52:  
      53:             _factoryThunk = () => controllerFactory;
      54:         }
      55:  
      56:         public void SetControllerFactory(Type controllerFactoryType)
      57:         {
      58:             if (controllerFactoryType == null)
      59:             {
      60:                 throw new ArgumentNullException("controllerFactoryType");
      61:             }
      62:             if (!typeof(IControllerFactory).IsAssignableFrom(controllerFactoryType))
      63:             {
      64:                 throw new ArgumentException(
      65:                     String.Format(
      66:                         CultureInfo.CurrentCulture,
      67:                         MvcResources.ControllerBuilder_MissingIControllerFactory,
      68:                         controllerFactoryType),
      69:                     "controllerFactoryType");
      70:             }
      71:  
      72:             _factoryThunk = delegate
      73:             {
      74:                 try
      75:                 {
      76:                     return (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
      77:                 }
      78:                 catch (Exception ex)
      79:                 {
      80:                     throw new InvalidOperationException(
      81:                         String.Format(
      82:                             CultureInfo.CurrentCulture,
      83:                             MvcResources.ControllerBuilder_ErrorCreatingControllerFactory,
      84:                             controllerFactoryType),
      85:                         ex);
      86:                 }
      87:             };
      88:         }
      89:     }
      90: }

     

     

    2、controller = factory.CreateController(this.RequestContext, controllername);

       此行代码,利用上一句得到一个ControllerFactory实例。将 RequestContext 和Controllername作为参数来调用 ControllerFactory类的CreateController方法,以此创建Controller实例并返回。

     

     

     

     

     

     

    至此,我们从请求的 路由数据中,得到 controllerName,又用controllerName,通过 ControllerFactory  获取到了真正的 Controller。

    ????

  • 相关阅读:
    github release 文件下载贼慢,干脆失败的解决方法
    windows 下sublime text 3 配置python 环境详解
    Ubuntu下安装并使用sublime text 3(建议:先安装Package controls 后在看本教程,否则可能会安装不了)
    将博客搬至CSDN
    signalr core客户端通过ssl连接服务的方式
    解决html导出pdf中文乱码问题的正确姿势
    记一次asp.net core 在iis上运行抛出502.5错误
    Elasticsearch 集群搭建
    bower私服部署
    体验Code::Blocks下的Windows GUI编程(32 bit and 64 bit)
  • 原文地址:https://www.cnblogs.com/acejason/p/3886968.html
Copyright © 2011-2022 走看看