好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ASP.NET MVC 3—MvcHandler、MvcHttpHandler

ASP.NET MVC 3—MvcHandler、MvcHttpHandler

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

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

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

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

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

         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;
        }

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

  public   virtual   void  PostResolveRequestCache(HttpContextBase context)
    {
        RouteData routeData =  this .RouteCollection.GetRouteData(context);
         if  (routeData !=  null )
        {
            IRouteHandler routeHandler = routeData.RouteHandler;
             if  (routeHandler ==  null )
            {
                 throw   new  InvalidOperationException( string .Format(CultureInfo.CurrentUICulture, 
 			 SR.GetString( "UrlRoutingModule_NoRouteHandler" ),  new   object [0]));
            }
             if  (!(routeHandler  is  StopRoutingHandler))
            {
                RequestContext requestContext =  new  RequestContext(context, routeData);
                context.Request.RequestContext = requestContext;
                IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
                 if  (httpHandler ==  null )
                {
                     throw   new  InvalidOperationException( string .Format(CultureInfo.CurrentUICulture, 
 			 SR.GetString( "UrlRoutingModule_NoHttpHandler" ),  new   object [] { routeHandler.GetType() }));
                }
                 if  (httpHandler  is  UrlAuthFailureHandler)
                {
                     if  (!FormsAuthenticationModule.FormsAuthRequired)
                    {
                         throw   new  HttpException(0x191, SR.GetString( "Assess_Denied_Description3" ));
                    }
                    UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current,  this );
                }
                 else 
                {
                    context.RemapHandler(httpHandler);
                }
            }
        }

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

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

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

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

         protected   void  Page_Load( object  sender, EventArgs e)
        {
            HttpContext.Current.RewritePath( "/Home/About" );
            IHttpHandler httpHandler =  new  MvcHttpHandler();
            httpHandler.ProcessRequest(HttpContext.Current);
        }

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

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

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于ASP.NET MVC 3—MvcHandler、MvcHttpHandler的详细内容...

  阅读:52次