博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler
阅读量:6995 次
发布时间:2019-06-27

本文共 5706 字,大约阅读时间需要 19 分钟。

熟悉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程序中让你更加灵活使用用来解决一些问题。

 

参考:

转载于:https://www.cnblogs.com/lookbs/p/MVC-Handler.html

你可能感兴趣的文章
react设置innerHTML
查看>>
升级_宽视野Oracle图形升级(升级后dbca建库)—10.2.0.1.0提拔10.2.0.5.0
查看>>
对JavaScript优化及规范的一些感想
查看>>
eclipse中python文本字体大小设置
查看>>
单页Html及Android App供小孩学习常用汉字
查看>>
Android设置透明、半透明等效果
查看>>
IntelliJ IDEA导出Java 可执行Jar包
查看>>
问题-关于sharemem程序访问WEB出现内存错误处理
查看>>
Machine Learning Done Wrong
查看>>
(剑指Offer)面试题39:二叉树的深度
查看>>
C标签判断两个值是否相等
查看>>
苏州优步高级车资费标准和奖励政策
查看>>
如何將 MySQL 資料庫轉移到 Microsoft SQL Server 與 Azure SQL Database
查看>>
Andio Studio
查看>>
电容冲放电公式
查看>>
Codeforces Bubble Cup 8 - Finals [Online Mirror] F. Bulbo DP
查看>>
HTML5+NodeJs实现WebSocket即时通讯
查看>>
Gradle 载入中 Android 下一个.so档
查看>>
log4写完日志不会自动释放
查看>>
【学生信息管理系统】与后端系统接口
查看>>