上篇讲到 请求到达 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. python smtplib发送邮件遇到的认证问题

    python的smtplib模块主要是用来发送邮件的,使用起来比较方便. 使用程序发送邮件只需要写以下几行代码就OK了: #!/usr/bin/env python import smtplib s ...

  2. mysql 锁优化

    一.myisam存储引擎锁优化 1.合理理由读写优先级MyISAM 的表锁,写互相阻塞的表锁,默认系统是写优先,可改为读有先:low_priority_updates=1如果我们的系统是一个以读为主, ...

  3. opencv 处女作

    显示一幅图:主要是运用功能:imread namedWindow imshowimread:从字面意思我们就可以看懂,用来读取图片的:namedWindow:显然,我们也可以看到这是用来命名窗口名称的 ...

  4. Q_OBJECT

    所有QObject的派生类在官方文档中都推荐在头文件中放置宏Q_OBJECT,那么该宏到底为我们做了哪些工作?在qobjectdef.h中有下面的代码: #define Q_OBJECT \ publ ...

  5. Clone

    Clone: 构建一个对象的时候,是不是一定要调用构造函数! package com.edu.test; public class Zhenzhen implements Cloneable{ pub ...

  6. 数据导出Excel中文乱码

    数据导出到EXCEL提供用户下载,当记录数大于5行时不会出现乱码.但只要不退出Excel,再删除除记录,当记录数小于5行时,导出也不会出现乱码.当然一旦退出Excel再导出就会出现乱码了. 可以试试 ...

  7. Oracle数据库备份 expdp/impdp导出导入命令

    使用EXPDP和IMPDP时应该注意的事项: EXP和IMP是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用. EXPDP和IMPDP是服务端的工具程序,他们只能在ORACLE服务端使用, ...

  8. MyEclipse快捷键敏感设置

    对于一个程序员来说,敲代码没有快捷键是很难受的.自从我装了MyEclipse之后发现快捷键敏感性太差了比如说我打输出语句System.out.println();一般打syso就会有提示,但是我的My ...

  9. 第十三章:降维:主成分分析PCA

  10. Pointers and Dynamic Allocation of Memory

    METHOD 1: Consider the case where we do not know the number of elements in each row at compile time, ...