上篇讲到 请求到达 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()

xxxxxController\ControllerFactory

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。

????

004. Asp.Net Routing与MVC 之二: 请求如何激活Controller和Action的更多相关文章

  1. 003. Asp.Net Routing与MVC 之一: 请求如何到达MVC

    基础知识 本文用到的基础知识:URL.HttpModule 与 HttpHandler.IIS 的请求处理过程. URL HttpModule与HttpHandler IIS7.0的请求处理过程 OK ...

  2. 005. Asp.Net Routing与MVC 之三: 路由在MVC的使用

    上次讲到请求如何激活Controller和Action,这次讲下MVC中路由的使用.本次两个关注点: 遗留:ModelBinder.BindModel的过程 MVC中路由的使用 MVC 5中的Acti ...

  3. 001. Asp.Net Routing与MVC 之(基础知识):URL

    URL(Uniform Resoure Locator:统一资源定位器)是WWW页的绝对地址.URL地址格式排列为:scheme://host:port/path. 例如 http://www.zn. ...

  4. 002. Asp.Net Routing与MVC 之(基础知识):HttpModule 与 HttpHandler

    本文By 杨工. 一. Http.sys http.sys 从Win2003和WinXP SP2开始,就成为windows操作系统内核驱动程序,能够让任何应用程序通过它提供的接口,以http协议进行信 ...

  5. 在ASP.NET MVC 中获取当前URL、controller、action 、参数

    URL的获取很简单,ASP.NET通用:[1]获取 完整url (协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [2]获取 虚拟目录名 ...

  6. 在ASP.NET MVC 中获取当前URL、controller、action

    一.URL的获取很简单,ASP.NET通用: [1]获取 完整url (协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [2]获取 虚拟 ...

  7. asp.net mvc 使用ajax请求 控制器 (PartialViewResult)分部的action,得到一个分部视图(PartialView)的HTML,进行渲染

    在asp.net mvc 使用ajax请求获取数据的时候,我们一般是返回json或者xml,然后解析这些数据进行渲染,这样会比较麻烦,可以请求一个 分部action,返回一个分部视图 直接可以渲染,不 ...

  8. 在ASP.NET MVC 中获取当前URL、controller、action(转)

    URL的获取很简单,ASP.NET通用: [1]获取 完整url (协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [2]获取 虚拟目录 ...

  9. 如何在ASP.NET MVC 中获取当前URL、controller、action

    一.URL的获取很简单,ASP.NET通用: [1]获取 完整url (协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [2]获取 虚拟 ...

随机推荐

  1. 如何使cookie全站都生效?

    一个页面设置的cookie, 默认在其同级目录下,及子目录下可以读取. 如果想让cookie整站有效,可以在根目录下setcookie 也可以用第4个参数,来指定cookie生效路径 setcooki ...

  2. Sprint 3 回顾与总结 和团队贡献分 以及Sprint 1、2、3 总概

    团队情况: 团队名称:Heaven Fire 团队博客地址:https://home.cnblogs.com/u/gjpg/                         团队Github地址:ht ...

  3. 《CODE》书摘

    2016-11-08 14:59:16 可以说英语词汇就是一种编码. 2016-11-08 15:19:04 实际上任何两种不同的东西经过一定的组合都可以代表任何种类的信息. 2016-11-08 1 ...

  4. Ubuntu 14.04 更新源

    deb http://mirrors.163.com/ubuntu/ trusty main restricted universe multiversedeb http://mirrors.163. ...

  5. Javascript日期比较

    var date1=Date.parse("2014-9-3 11:40:14".replace(/-/g,"/")); var date2=Date.pars ...

  6. WinCE下读取注册表获得SD路径

    WinCE下读取注册表获得SD路径 [要点]WinCE注册表中[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\] 下键Folde ...

  7. Java实现Excel导入数据库,数据库中的数据导入到Excel

    private static void executeMethod(JobExecutionContext arg0) throws Exception{ try { TContrastService ...

  8. Win7 64位 VS2015环境编译Libpng

    第3次编译Libpng依然想不起任何东西,为了不浪费第4次的时间... http://libmng.com/pub/png/libpng.html http://www.zlib.net/ 解压两个压 ...

  9. MATLAB-octave中向量场图的可视化

    参考http://379910987.blog.163.com/blog/static/33523797201162223310546/ 设二维函数z=f(x,y),其中z为海拔,x为东西测向距离而y ...

  10. C#自旋的艺术

    CODE1: while (status == ServerStatus.Started) { if (*TaskLocker > 0) { for (int i = 0; i != *Leve ...