热门:网页模板.net视频教程JQueryMVCjsonExtJs源码示例三级联动JQuery菜单
您现在的位置:.Net中文社区>> .Net编程>>正文内容

ASP.NET MVC 3—一切的开始MvcHandler、MvcHttpHandler

发布时间:2011年05月26日点击数: 佚名

在ASP.NET MVC3里面,一次用户请求是如何开始的呢?

如果下载了MVC的源代码进行调试,一般来说会发现开始于MvcHandler,简单看下MvcHandler的代码,主要就是通过控制器的工厂接受控制器的实例,并使用控制器进行进一步处理,那么MvcHandler是如果被创建,如何被调用执行的?

首先看看MvcHandler的构造函数,是没有无参的构造函数,显然看来MvcHandler单干是有点难度了。直接查找MvcHandler的所有引用,很容易在MvcRouteHandler中可以找到:

  1. protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { 
  2.  
  3.     requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext)); 
  4.  
  5.     return new MvcHandler(requestContext); 
  6.  

而且使用MvcHandler构造函数的地方有且仅有这么一个,明显我们找到我们想要的东西了。

接下来就需要弄清楚MvcRouteHandler的GetHttpHandler什么时候执行的,看源代码的时候,“查找所有引用”是很好用的功能,在RouteCollectionExtensions里面可以看到:

  1. public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, 
  2.  
  3. t constraints, string[] namespaces) { 
  4.  
  5.     if (routes == null) { 
  6.  
  7.         throw new ArgumentNullException("routes"); 
  8.  
  9.     } 
  10.  
  11.     if (url == null) { 
  12.  
  13.         throw new ArgumentNullException("url"); 
  14.  
  15.     } 
  16.  
  17.  
  18.  
  19.     Route route = new Route(url, new MvcRouteHandler()) { 
  20.  
  21.         Defaults = new RouteValueDictionary(defaults), 
  22.  
  23.         Constraints = new RouteValueDictionary(constraints), 
  24.  
  25.         DataTokens = new RouteValueDictionary() 
  26.  
  27.     }; 
  28.  
  29.  
  30.  
  31.     if ((namespaces != null) && (namespaces.Length > 0)) { 
  32.  
  33.         route.DataTokens["Namespaces"] = namespaces; 
  34.  
  35.     } 
  36.  
  37.  
  38.  
  39.     routes.Add(name, route); 
  40.  
  41.  
  42.  
  43.     return route; 
  44.  

这个就比较好理解了,MvcRouteHandler实现了 IRouteHandler接口,因此可以与路由模块进行集成,当我们在Global.asax文件中使用MapRoute方法时,会向路由模块注册 MvcRouteHandler实例,当MvcRouteHandler被调用的时候,会创建RequestContext实例产生MvcHandler 的实例,并使用MvcHandler实例进一步进行处理。查看在UrlRoutingModule的代码可以看到:

  1. public virtual void PostResolveRequestCache(HttpContextBase context) 
  2.  
  3.    { 
  4.  
  5.        RouteData routeData = this.RouteCollection.GetRouteData(context); 
  6.  
  7.        if (routeData != null
  8.  
  9.        { 
  10.  
  11.            IRouteHandler routeHandler = routeData.RouteHandler; 
  12.  
  13.            if (routeHandler == null
  14.  
  15.            { 
  16.  
  17.                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture,  
  18.  
  19.         SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0])); 
  20.  
  21.            } 
  22.  
  23.            if (!(routeHandler is StopRoutingHandler)) 
  24.  
  25.            { 
  26.  
  27.                RequestContext requestContext = new RequestContext(context, routeData); 
  28.  
  29.                context.Request.RequestContext = requestContext; 
  30.  
  31.                IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); 
  32.  
  33.                if (httpHandler == null
  34.  
  35.                { 
  36.  
  37.                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture,  
  38.  
  39.         SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[] { routeHandler.GetType() })); 
  40.  
  41.                } 
  42.  
  43.                if (httpHandler is UrlAuthFailureHandler) 
  44.  
  45.                { 
  46.  
  47.                    if (!FormsAuthenticationModule.FormsAuthRequired) 
  48.  
  49.                    { 
  50.  
  51.                        throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3")); 
  52.  
  53.                    } 
  54.  
  55.                    UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this); 
  56.  
  57.                } 
  58.  
  59.                else 
  60.  
  61.                { 
  62.  
  63.                    context.RemapHandler(httpHandler); 
  64.  
  65.                } 
  66.  
  67.            } 
  68.  
  69.        } 

到此为止MvcHandler的整个创建过程就差不都已经弄清楚,那么接下来继续介绍MvcHttpHandler,也许有人会问既然已经有MvcHandler了为什么还需要MvcHttpHandler呢?

其实前面也提到过了,MvcHandler没有无参的构造函数,因此即使MvcHandler实现了 IHttpHandler接口,在IIS中也不能将其映射为某类文件扩展名的处理程序,需要结合路由模块使用。那么MvcHttpHandler就提供了 不通过路由模块的情况下直接处理映射的处理程序。

至于如何将某类文件扩展名映射到一个MVC处理程序,在此就不多做介绍,但MvcHttpHandler带无参的构造函数,而且继承UrlRoutingHandler类实现了IHttpHandler接口,因此可以在ASP.NET程序中灵活的使用用来解决一些问题。

例如创建一个普通的MVC3项目,但在项目中添加一个WebForm页面TestPage.aspx,在页面的后台文件TestPage.aspx.cs文件中添加如下代码:

  1. protected void Page_Load(object sender, EventArgs e) 
  2.  
  3.  
  4.     HttpContext.Current.RewritePath("/Home/About"); 
  5.  
  6.     IHttpHandler httpHandler = new MvcHttpHandler(); 
  7.  
  8.     httpHandler.ProcessRequest(HttpContext.Current); 
  9.  

然后直接访问/TestPage.aspx页面,会发现实际访问返回了/Home/About页面。

调试查看访问/TestPage.aspx执行的过程,还会发现最终还是使用到MvcHandler,至于为什么会这样子?有兴趣的话可以看下UrlRoutingHandler的ProcessRequest的逻辑就能够理解了。

本站热点业务

更多模板/案例展示

关于我们 | 联系我们 | 团队日志 | 网站地图 | 网站合作