MVC系列(9) MVC如何在Pipeline中接管请求的

上个章节我们讲到了,可以在HttpModules初始化之前动态添加Route的方式来自定义自己的HttpHandler,最终接管请求的,那MVC是这么实现的么?本章节我们就来分析一下相关的MVC源码来验证一下我们的这个问题。

先创建一个MVC3的Web Application,选择默认的模板以便创建以后就默认包含HomeController和AccountController。我们知道MVC要先接管请求才能通过这些Controller来处理,那我们先去Global.asax.cs文件里看代码(定义接管请求要在初始化HttpModule之前,所以只能到这里来找代码(或者是利用WebActivator之类的特性来动态添加),Global.asax.cs文件里代码很少,但是有我们需要的东西,首先在Application_Start的方法里发现一行代码:

RegisterRoutes(RouteTable.Routes);

这行代码,看调用的方法名称RegisterRoutes是注册Route的意思,但是为什么参数却是全局的RouteTable.Routes集合呢?找到RegisterRoutes方法来看看具体的内容:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}

该方法有2行代码,第一行是忽略一个Route(我们先不看这个),第二行是使用MapRoute方法注册一个新的Route,默认是映射到Home Controller的Index Action上,我们可能想到了,RouteCollection(也就是刚才传入的RouteTable.Routes)的MapRoute方法就是提供我们所说的接管请求的入口,但是如何把MVC自己的HttpHandler传进去的呢?我们Go to一下这个MapRoute方法(需要安装ReShaper来查找MVC的源码),调整到了MVC的 RouteCollectionExtensions类,发现MapRoute并不是RouteCollection自带的方法,而是在MVC源码里提供的一个扩展方法,代码如下:

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
    if (routes == null)
    {
        throw new ArgumentNullException("routes");
    }
    if (url == null)
    {
        throw new ArgumentNullException("url");
    }  

    Route route = new Route(url, new MvcRouteHandler())
    {
        Defaults = new RouteValueDictionary(defaults),
        Constraints = new RouteValueDictionary(constraints),
        DataTokens = new RouteValueDictionary()
    };  

    if ((namespaces != null) && (namespaces.Length > 0))
    {
        route.DataTokens["Namespaces"] = namespaces;
    }  

    routes.Add(name, route);  

    return route;
}

该代码的主要作用是new一个新的Route,然后将该Route添加到我们刚才提到的静态集合RouteTable.Routes里,以便后期查找Handler的时候使用,OK,这一步符合我们前面章节的分析。

接下来看,Route是如何new出来的,代码里的参数传入的分别是我们知道的url,以及一个MVCRouteHandler的实例,这一步也符合我们前面的分析,那我们来看一下MVCRouteHandler的GetHttpHandler方法是如何实现的获取MVCHandler的:

public class MvcRouteHandler : IRouteHandler {
    private IControllerFactory _controllerFactory;  

    public MvcRouteHandler() {
    }  

    public MvcRouteHandler(IControllerFactory controllerFactory) {
        _controllerFactory = controllerFactory;
    }  

    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
        requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
        return new MvcHandler(requestContext);
    }  

    protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext) {
        string controllerName = (string)requestContext.RouteData.Values["controller"];
        IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
        return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
    }  

    #region IRouteHandler Members
    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
        return GetHttpHandler(requestContext);
    }
    #endregion
}

看以上的粗体代码,MvcRouteHandler在实现了IRouteHandler的GetHttpHandler,该方法调用了 MvcRouteHandler自身定义的GetHttpHandler虚方法,而在这个虚方法里我们看到了一个非常重要而又期待已久的代码——返回 MvcHandler的实例,大概看一下MvcHandler这个类,得到它就是我们所猜想的:继承于IHttpHandler接口的一个类,并且也继承了 IHttpAsyncHandler接口,我们先不管MvcHandler内部是如何实现的,但我们前面几章节的全部分析终于得到了验证,也就说在这里得到了Mvc的专用处理Handler,然后调用它的BeginProcessRequest方法进入Mvc自身的Pipeline进行处理了。

至此,我们终于弄明白了Mvc在整个ASP.NET Runtime是如何接管请求的了,也应该大概清楚整个ASP.NET Runtime的运行机制了,至于MvcHandler的实现方式,我们会在后面的很多章节逐一给大家分析每行代码,今天我们还有一个小任务,那就是:看完了Mvc的实现机制,我们能否自己来写一个自定义的HttpHandler通过Route动态注册进去,来实现我们自己的自定义扩展,我们来尝试着做一下吧。

本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/webkf/aspx/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索方法
, 代码
, route
, routing
, 一个
Routes
http pipeline 请求、spring mvc ajax请求、spring mvc post请求、spring mvc 异步请求、spring mvc 请求转发,以便于您获取更多的相关知识。

时间: 2024-10-22 06:01:31

MVC系列(9) MVC如何在Pipeline中接管请求的的相关文章

MVC系列(5) Http Pipeline详细分析(下)

接上面的章节,我们这篇要讲解的是Pipeline是执行的各种事件,我们知道,在自定义的HttpModule的Init方法里,我们可以添加自己的事件,比如如下代码: public class Test : IHttpModule { public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); context.AuthenticateReques

MVC系列(4) Http Pipeline详细分析(上)

继续上一章节的内容,通过HttpApplicationFactory的GetApplicationInstance静态方法获取实例,然后执行该实例的BeginProcessRequest方法进行执行余下的Http Pipeline 操作,代码如下: // Get application instance IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context); 那GetApplicationInstanc

MVC系列(8) UrlRouting的理解

根据对Http Runtime和Http Pipeline的分析,我们知道一个ASP.NET应用程序可以有多个HttpModuel,但是只能有一个HttpHandler,并且通过这个 HttpHandler的BeginProcessRequest(或ProcessRequest)来处理并返回请求,前面的章节将到了再 MapHttpHandler这个周期将会根据请求的URL来查询对应的HttpHandler,那么它是如何查找的呢? 一起我们在做自定义HttpHandler的时候,需要执行URL以及

爱上MVC系列~目录

MVC3配合Razor视图引擎使得我们在开发项目中更加快捷,以下是我在项目开发过程中整理的一些笔记,和大家一起分享一下 爱上MVC系列~目录 爱上MVC~Razor引擎时,在遍历中巧用Output.Write方法 爱上MVC~开发Areas模块时需要注意一下路由问题 爱上MVC~实体级标准验证 爱上MVC系列~PartialView()与View()真的一样吗? 爱上MVC系列~手动向路由表扔数据,不影响当前URL路由配对 爱上MVC系列~使用Func<string, HelperResult>

Asp.net MVC2.0系列文章-MVC简介篇

使用微软VS工具开发Web应用程序主要有两种方式:一种是常用的创建Asp.net Web Forms,另外一种就是今天着重介绍的Asp.net MVC. Web Forms有两部分组成:Aspx檔以及后台代码aspx.cs文件. 文章-MVC简介篇-"> Web Forms优点是: HTML接口与业务逻辑分开 丰富的服务器控件,加速了开发速度 数据绑定技术 基于事件的程序模型 用户控件和第三方控件技术 什么是Asp.net MVC? ASP.NET MVC Framework是微软在ASP

mvc get无刷新页面绑定table中数据

问题描述 mvc get无刷新页面绑定table中数据 我刚接触MVC 我想使用GET方式对Tbale中的数据进行刷新?get方式最好可以返回的是ViewBag?谁弄过啊???

grep 命令系列:如何在 UNIX 中根据文件内容查找文件

grep 命令系列:如何在 UNIX 中根据文件内容查找文件 为了完成课程作业,我写了很多 C 语言代码并把它们保存为 /home/user/c/*.c 和 *.h.那么在 UNIX shell 窗口中我如何能通过字符串或者单词(例如函数名 main())文件内容来查找文件呢? 你需要用到以下工具: [a] grep 命令 : 输出匹配模式的行. [b] find 命令: 在目录层次中查找文件. 使用 grep 命令根据内容查找文件 输入以下命令: grep 'string' *.txt gre

spring mvc 使用拦截器和在controller中使用if语句的服务器资源使用率和效率对比?

问题描述 spring mvc 使用拦截器和在controller中使用if语句的服务器资源使用率和效率对比? 就比如 用户权限问题,一个没有权限的用户要访问只有管理员才有权限访问的请求地址 使用框架配的拦截器的方式与在controller或者userServiceimpl中使用if语句进行权限访问的控制方式,两种方式的服务器资源使用率和执行效率方面比较情况是怎样的? 解决方案 个人观点,这就像数据库的,lazy模式和非lazy模式差不多

Spring MVC 原子学习法 之 web.xml 中的配置

Spring MVC  原子学习法 之  web.xml 中的配置 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 由上图可以看得出,Spring-MVC 应用的配置要从 JavaWeb 的配置