前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎。这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之处,还希望大家斧正,博主感激不尽!
本文原创地址:
一、MVC原理解析最近园子里Asp.Net Core火了一阵,不管微软的开源动作有多么迟缓,还是希望微软能够给力一次。作为Core的主要Web框架——MVC,虽然已经开源,但是读起来着实费劲,并且感觉很多核心部件都找不到。于是只能通过Reflector去反编译MVC5的组件以及参考博客园Fish Li等大神的文章去学习下MVC5的原理。
10月26日更新:感谢园友Adming在评论中提醒,原来Asp.net Core Mvc和Asp.net Mvc 5的原理已经完全不同,难怪在Core Mvc的源码里面已经找不到MvcHandler、UrlRoutingModule等核心部件了呢,此系列文章就先学习下MVC5的原理,等以后有空了再来研究Core MVC吧。
Asp.Net Core MVC的开源地址:https://github.com/aspnet/Mvc
Asp.net MVC的开源地址:
1、MVC原理之前的文章有介绍MVC的路由机制,其实路由机制算是MVC的原理的核心之一。在此我们还是要不厌其烦再来谈谈整个过程,因为这是理解MVC原理不可逾越的鸿沟。当我们收到一个URL的请求时,服务端收到请求,主要经历以下几个步骤:
附上一张大致的流程图:
纵观整个过程,看上去很复杂,各种对象缠绕,看得人晕晕的。其实如果你静下心来仔细研读MVC的源码你会发现其实并没有想像中的那般复杂,请有点耐心听博主慢慢道来。
1、整个过程有两个核心的组件,文中博主用红色标记了出来:UrlRoutingModule和MvcHandler,上文提到的各个过程都和两个组件有紧密的联系。而这两个组件分别继承至IHttpModule和IHttpHandler接口,熟悉Asp.net管线事件的朋友应该会记得这两个接口,在管道事件里面这两个接口扮演着重要角色。要理解MVC的上述原理,必须要先理解这两类接口的原理以及使用。
2、UrlRoutingModule的作用可以理解为通过一系列的与路由相关的组件去解析当前请求的Controller与Action名称,其实简单点理解,比如我们请求:8080/Home/Index这个url的时候,UrlRoutingModule拦截到这个请求,然后通过一系列的方式得到这里的“Home”和“Index”,这样理解有没有简单一点呢。
3、MvcHandler的作用就更加直接,上述通过拦截组件得到了请求的Controller和Action的名称,MvcHandler组件将当前请求的Controller名称反射得到对应的控制器对象,然后执行对应的Action方法。比如还是上述:8080/Home/Index这个请求,通过字符串“Home”反射成为Home这个类型的控制器对象,然后调用这个对象的Index()方法。
4、综上,联合这两个组件来理解,UrlRoutingMudule组件的主要作用是解析当前的Controller与Action名称,MvcHandler的作用是将得到的Controller名称激活,得到具体的Controller对象,然后执行对应的Action方法。
所以,要理解MVC的原理,必须要了解这两个组件的基本原理以及作用。下面就根据这两个组件分别展开说明,相信理解了下面的内容,你对mvc的原理会有一个新的认识。
二、HttpHandler上文说过MvcHandler是继承至IHttpHandler接口的!为什么这里大标题会用HttpHandler而不是MvcHandler呢?因为博主觉得,HttpHandler实在是太重要了,首先得理解了HttpHandler这么一个大的东西,然后再来看具体的MvcHandler才有意义。
1、HttpHandler、IHttpHandler、MvcHandler的说明总而言之,HttpHandler只是一个逻辑称谓,它并不具体存在。而IHttpHandler和MvcHandler是.net framework里面具体存在的接口和实现类,是前者的表现形式。
2、IHttpHandler解析 2.1、Asp.net管线事件简易说明做过Webform开发的园友应该记得,在asp.net的页面生命周期里面,一共有24个管线事件,完整的管线事件可参考MSDN文档:
在处理该请求时将由 HttpApplication 类执行以下事件。 希望扩展 HttpApplication 类的开发人员尤其需要注意这些事件。 1. 对请求进行验证,将检查浏览器发送的信息,并确定其是否包含潜在恶意标记。 有关更多信息,请参见 ValidateRequest 和脚本侵入概述。 2. 如果已在 Web.config 文件的 UrlMappingsSection 节中配置了任何 URL,则执行 URL 映射。 3. 引发 BeginRequest 事件。 4. 引发 AuthenticateRequest 事件。 5. 引发 PostAuthenticateRequest 事件。 6. 引发 AuthorizeRequest 事件。 7. 引发 PostAuthorizeRequest 事件。 8. 引发 ResolveRequestCache 事件。 9. 引发 PostResolveRequestCache 事件。 10. 根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理。 如果该请求针对从 Page 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。 11. 引发 PostMapRequestHandler 事件。 12. 引发 AcquireRequestState 事件。 13. 引发 PostAcquireRequestState 事件。 14. 引发 PreRequestHandlerExecute 事件。 15. 为该请求调用合适的 IHttpHandler 类的 ProcessRequest 方法(或异步版 IHttpAsyncHandler.BeginProcessRequest)。 例如,如果该请求针对某页,则当前的页实例将处理该请求。 16. 引发 PostRequestHandlerExecute 事件。 17. 引发 ReleaseRequestState 事件。 18. 引发 PostReleaseRequestState 事件。 19. 如果定义了 Filter 属性,则执行响应筛选。 20. 引发 UpdateRequestCache 事件。 21. 引发 PostUpdateRequestCache 事件。 22. 引发 EndRequest 事件。 23. 引发 PreSendRequestHeaders 事件。 24. 引发 PreSendRequestContent 事件。
Asp.net管线事件说明