上篇讲到 请求到达 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. PHP高并发高负载系统架构

    PHP高并发高负载系统架构 1.为什么要进行高并发和高负载的研究 1.1.产品发展的需要 1.2.公司发展的需要 1.3.当前形式决定的 2.高并发和高负载的约束条件 2.1.硬件 2.2.部署 2. ...

  2. C# this和base的使用

    namespace THISORBASE { //参考地址:http://blog.sina.com.cn/s/blog_7300c7d90100rs20.html /*这个时候,派生类和基类的_st ...

  3. sqlserver2012 表分区

    无论是新建数据库,还是现有的问题,都可以执行表分区的操作. 1.在数据库中点鼠标右键点击属性,在选择页,选中文件栏,在数据库文件列表中,可以看到现有的数据库文件逻辑名称.文件类型.初始大小.保存位置等 ...

  4. css+js定位到屏幕中间

    ex:让一个div始终显示在屏幕中间 一. css:#idName{position: absolute;z-index: 999;width: ?px;margin-top: ?px;}//此处的初 ...

  5. C++面试中关于sizeof问题总结

    原文:http://blog.sina.com.cn/s/blog_7c983ca60100yfdv.html#SinaEditor_Temp_FontName (1)      sizeof是操作符 ...

  6. [转]SQL Server表锁定原理以及如何解除锁定

    2010年10月13日 12:46 来源:部松昌的博客 作者:部松昌 编辑:胡铭娅 一: 下面以AdventureWorks2008为示例数据库做简要的说明,过滤掉一般的数据库的共享锁, 作为示例必须 ...

  7. D3(Data-Driven-Document)中的一些细节

    不定期更新,给自己看,如果能帮到别人,我也很开心. 1)好像 function中默认的两个参数d,和i,如果只有i,则i实际上是d 的内容. lineG.selectAll("line&qu ...

  8. zTree+EasyUi做权限遇到的小问题

    最近需要做一个zTree+EasyUi的权限管理系统,以前有过接触,在做这一块时,用到了ztree,树来加载咱们的菜单栏,后台获取登录用户信息的权限列表,转换成json对象来加载到咱们的树当中,代码如 ...

  9. Sublime+Golang Plugin

    很喜欢在Sublime开发Golang程序,主要是要一个Sublime Golang Plugin, 可以给代码autocomplement.相当的棒! 1.安装Sublime https://www ...

  10. css中关于position属性的探究(原创)

    关于position属性的设置,头脑中一直觉得不是很清楚,所以借助这次机会单独自己测试了一下,记作学习笔记.   首先,css的position属性包含下面四种设置情况: static:默认属性.指定 ...