熟悉WebForm开发的朋友一定都知道,Page类必须实现一个接口,就是IHttpHandler。HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET Framework调用HttpHandler的ProcessRequest成员方法来对这个HTTP请求进行真正的处理,真正地对客户端请求的服务器页面做出编译和执行。归根结底,Asp.Net所有的HTTP请求最后都是由IHttpHandler的实现来处理的,Asp.Net MVC框架当然也不例外。下面就从MvcRouteHandler、MvcHandler和MvcHttpHandler三个常见的Handler类来浅析一下MVC是怎么和IHttpHandler联系起来进行HTTP请求处理的。

1、MvcRouteHandler

在MVC中MvcApplication通常在Application_Start事件里实现RegisterRoutes方法:

        protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(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
); }

这个方法非常重要,因为正是从这里开始,Asp.Net应用程序可以和Asp.Net URL Routing组件完美结合起来实现Url优化(MVC和WebForm都可以,可以参考dudu的这一篇)。

从MVC源码入手,我们发现RouteCollection的MapRoute扩展方法最终都是通过RouteCollectionExtensions的一个静态方法实现的:

        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")]
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;
}

大家注意这一行:   Route route = new Route(url, new MvcRouteHandler()),正是通过MvcRouteHandler(其实从命名就可以猜到),Asp.Net的URL Routing组件就和IHttpHandler有了关联。到这里我们猜测,MvcRouteHandler一定和IHttpHandler有关系(甚至它可能就是IHttpHandler的一个具体实现),而且URL Routing组件最后一定映射到一个IHttpHandler处理程序来处理相应的HTTP请求。我们来查看MvcRouteHandler具体源码实现印证一下自己的看法:

/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/ namespace System.Web.Mvc
{
using System.Web.Routing;
using System.Web.SessionState; 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没有继承实现IHttpHandler接口,而是继承了IRouteHandler接口,但是我们欣喜发现IRouteHandler接口的唯一方法GetHttpHandler返回了一个IHttpHandler,这实在是太让人感到意料之中的一阵激动了。

2、MvcHandler

继续上面MvcRouteHandler的源码,我们发现MvcRouteHandler具体实现GetHttpHandler的时候最后new了一个MvcHandler对象返回:

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

也就是说MvcHandler是IHttpHandler子类确定无疑了。然后查看MvcHandler源码,发现MvcHandler继承实现了IHttpAsyncHandler, IHttpHandler, IRequiresSessionState三个无比熟悉的接口。而这三个接口如果都实现了,在MVC框架下是不是任何http请求就可以通吃了呢?从MSDN我们得知,事实不是这样的:

注意,即使 MvcHandler 实现 IHttpHandler,也不能将其映射为处理程序(例如.mvc 文件扩展名),因为该类不支持无参数构造函数。 (它唯一的构造函数需要一个 RequestContext 对象)

但是,还好,我们还有MvcHttpHandler。

3、MvcHttpHandler

如你所知,MvcHttpHandler可以“弥补”MvcHandler的不足,为什么这样说呢?其实2中也提到过了,MvcHandler没有无参的构造函数,因此即使MvcHandler实现了 IHttpHandler接口,在IIS中也不能将其映射为某类文件扩展名的处理程序,需要结合路由模块使用。

而MvcHttpHandler就提供了不通过路由模块的情况下直接处理映射的处理程序。通过查看MvcHttpHandler源码我们发现,MvcHttpHandler继承实现了UrlRoutingHandler, IHttpAsyncHandler, IRequiresSessionState接口,而UrlRoutingHandler继承自IHttpHandler。MvcHttpHandler带无参的构造函数(也就是说我们可以直接new一个MvcHttpHandler无参数对象?不用担心上下文?希望这里的解释不是令人感到费解),而且继承自UrlRoutingHandler类实现了IHttpHandler接口,因此可以在ASP.NET程序中让你更加灵活使用用来解决一些问题。

参考:

http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvcroutehandler.aspx

http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvchandler.aspx

http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvchttphandler.aspx

从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler的更多相关文章

  1. 【转】从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler

    原文:http://www.cnblogs.com/jeffwongishandsome/archive/2012/01/08/2316521.html 熟悉WebForm开发的朋友一定都知道,Pag ...

  2. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  3. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  4. Struts2源码浅析-ConfigurationProvider

    ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...

  5. (转)【深入浅出jQuery】源码浅析2--奇技淫巧

    [深入浅出jQuery]源码浅析2--奇技淫巧 http://www.cnblogs.com/coco1s/p/5303041.html

  6. HashSet其实就那么一回事儿之源码浅析

    上篇文章<HashMap其实就那么一回事儿之源码浅析>介绍了hashMap,  本次将带大家看看HashSet, HashSet其实就是基于HashMap实现, 因此,熟悉了HashMap ...

  7. Android 手势识别类 ( 三 ) GestureDetector 源码浅析

    前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...

  8. Android开发之Theme、Style探索及源码浅析

    1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...

  9. 【深入浅出jQuery】源码浅析2--使用技巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

随机推荐

  1. 微信企业号 获取AccessToken

    目录 1. AccessToken介绍 2. 示例代码 1. AccessToken介绍 1.1 什么是AccessToken AccessToken即访问凭证,业务服务器每次主动调用企业号接口时需要 ...

  2. 【.net 深呼吸】细说CodeDom(4):类型定义

    上一篇文章中说了命名空间,你猜猜接下来该说啥.是了,命名空间下面就是类型,知道了如何生成命名空间的定义代码,之后就该学会如何声明类型了. CLR的类型通常有这么几种:类.接口.结构.枚举.委托.是这么 ...

  3. 阿里签名中URLEncode于C#URLEncod不同之处

    问题 如上图所示,阿里云的PercentEncode 转换! 为 %21 PercentEncode 源码为: package com.aliyuncs.auth; import java.io.Un ...

  4. bootstrap-fileinput 简单使用

    bootstrap-fileinput 是一款图片/文件上传 bootstrap 插件,简单示例代码: <!DOCTYPE html> <html> <head> ...

  5. zookeeper源码分析之六session机制

    zookeeper中session意味着一个物理连接,客户端连接服务器成功之后,会发送一个连接型请求,此时就会有session 产生. session由sessionTracker产生的,sessio ...

  6. WebGIS中等值面展示的相关方案简析

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 等值面是气象.环保等相关项目上常用到的效果展示.在传统的CS项 ...

  7. android studio你可能忽视的细节——启动白屏?drawable和mipmap出现的意义?这里都有!!!

    android studio用了很久了,也不知道各位小伙伴有没有还在用eclipse的,如果还有,楼主真心推荐转到android studio来吧,毕竟亲儿子,你会知道除了启动速度稍微慢些,你找不到一 ...

  8. JavaScript作用域

    JavaScript作用域 JavaScript作用域一直是前端开发的难题,现在只要用五句话就可解决. 一.“JavaScript中无块级作用域” 在Java或C#中存在块级作用域,即:大括号也是一个 ...

  9. Lucene4.4.0 开发之排序

    排序是对于全文检索来言是一个必不可少的功能,在实际运用中,排序功能能在某些时候给我们带来很大的方便,比如在淘宝,京东等一些电商网站我们可能通过排序来快速找到价格最便宜的商品,或者通过排序来找到评论数最 ...

  10. windows10安装mysql5.7.17是这样安装的吗?

    操作 全允许