上篇讲到 请求到达 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. Chrome 插件集推荐

    在前端这个行业里面,浏览器担任着及其重要的角色.今天我们可以选择的浏览器有很多,Chrome,Firefox,IE,Safari… 为了能获得更佳的开发体验,大家更多地选择 Chrome.今天介绍下我 ...

  2. jQuery的ajax问题

    Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to th ...

  3. 20145318 GDB调试汇编堆栈分析

    20145318 GDB调试汇编堆栈分析 代码 #include<stdio.h> short addend1 = 1; static int addend2 = 2; const sta ...

  4. Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)

    思路: dfs序其实是很水的东西.  和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的 ...

  5. js 正则验证输入框只允许输入正实数和正整数和负整数

    <input onkeyup="this.value=this.value.replace(/[^0-9.]/g,'')">  (正实数) <input onke ...

  6. beanstalkd----协议

    Beanstalkd中文协议 总括 beanstalkd协议基于ASCII编码运行在tcp上.客户端连接服务器并发送指令和数据,然后等待响应并关闭连接.对于每个连接,服务器按照接收命令的序列依次处理并 ...

  7. 基音周期提取2-基于线性相关系数的Matlab实现

    基音周期提取2-基于线性相关系数的Matlab实现 基音周期提取结果 图1 基音提取结果 算法说明 线性相关系数 也称"皮尔逊积矩相关系数"(Pearson product-mom ...

  8. Java程序,取随机数的两种实现方法

    1.随机数的第一种程序(取0-9的整型随机数) public class random_1 { public static void main(String[] args) { Random r=ne ...

  9. 为Page添加INotifyPropertyChanged功能

    在Page页面里面, DataContext 更新后,前台数据要求会自动更新. 但前台的绑定如果用x:bind 语法. 它要求强类型.直接关联到DataContext上就不行了. 需要为Page 添加 ...

  10. Android密码约束规则例子一

    Android常用的一个密码规则 (一)密码必须是8至16位:(二)密码必须包含英文字母和数字:(三)密码不能包含4位连续相同的字符,如0000或AAAA:(四)密码不能包含4位连续递增或连续递减的数 ...