ASP.NET的运行原理
当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的页面类型为其加载相应的.dll文件,然后在处理过程中将这条请求发送给能够处理这个请求的模块。在ASP.NET 3.5中,这个模块叫做HttpHandler(HTTP处理程序组件),之所以.aspx文件可以被服务器处理,就是因为在服务器端有默认的HttpHandler专门处理.aspx文件。IIS在将这条请求发送给能够处理这个请求的模块之前,还需要经过一些HttpModule的处理,这些都是系统默认的Modules(用于获取当前应用程序的模块集合),在这个HTTP请求传到HttpHandler之前要经过不同的HttpModule的处理。这样做的好处,一是为了一些必需的过程,二是为了安全性,三是为了提高效率,四是为了用户能够在更多的环节上进行控制,增强用户的控制能力。ASP.NET 3.5运行原理如图1.1所示。
图1.1 ASP.NET 3.5运行原理
说明:HttpModule模块是一个组件,可以注册为ASP.NET 3.5请求生命周期的一部分,当处理该组件时,该组件可以读取或更改请求或响应。HttpModule模块通常用于执行需要监视每个请求的特殊任务,如安全或站点统计信息。
(PS:
HttpModule 概述:
暂时先不考虑我们自己实现Http Module的情况。在.Net中,Http Module 是实现了IHttpModule接口的程序集。IHttpModule 接口本身并没有什么好大写特写的,由它的名字可以出,它不过是一个普普通通的接口而已。实际上,我们关心的是实现了这些接口的类,如果我们也编写代码实现了这个接口,那么有什么用途。一般来说,我们可以将Asp.Net中的事件分成三个级别,最顶层是 应用程序级事件、其次是页面级事件、最下面是控件级事件,事件的触发分别与 应用程序周期、页面周期、控件周期紧密相关。而 Http Module 的作用是与应用程序事件 密切相关的。
我们通过Http Module在Http请求管道(Pipeline)中注册期望对应用程序事件做出反应的方法,在相应的事件触发的时候(比如说BeginRequest事件,它在应用程序收到一个Http请求并即将对其进行处理时触发),便会调用Http Module注册了的方法,实际的工作在这些方法中执行。.Net 本身已经有很多的Http Module,其中包括 表单验证Module(FormsAuthenticationModule), Session 状态Module(SessionStateModule),输出缓存Module (OutputCacheModule)等。
更多了解:http://www.cnblogs.com/jimmyzhang/archive/2007/11/25/971878.html
)
ASP.NET 3.5运行机制如图1.2所示。
通常情况下,ASP.NET框架搭建在Windows Server(服务器版操作系统)+IIS(Web服务器,是Internet信息服务管理器的英文缩写)环境中,在安装.NET Framework时,安装程序将会在IIS中注册ASP.NET所需的ISAPI扩展(aspnet_isapi.dll),这就使得作为ASP.NET宿主的IIS在接收到客户端的HTTP请求后,将响应请求的控制权交给ASP.NET运行。
ASP.NET运行时接收到请求后,会判断站点是否为第一次被访问,如果是第一次访问,则运行初始化工作(如加载Bin目录中的DLL动态链接库,读取Web.Config网站配置文件,初始化HttpApplication实例,编译和加载Global.asax文件等)。ASP.NET运行时还负责创建请求响应线程的HttpContext上下文实例和创建承载响应结果的HttpTextWriter实例。然后,ASP.NET运行时寻找合适的HttpHandler(通常就是具有的ASP.NET页面)处理HTTP请求,并等HttpHandler返回请求处理结果。最后,ASP.NET运行时在完成一些后续工作之后,如保存Session、异常处理,再通过IIS把响应结构返回给客户端。
图1.2 ASP.NET 3.5运行机制
注意:ASP.NET ISAPI工作的主要任务就是安排ASPNET_WP.exe处理请求,并监视ASPNET_ WP.exe进程的执行情况,如果ASPNET_WP.exe进程不能完成任务,ASP.NET ISAPI就安排一个新的ASPNET_WP.exe来处理工作。ASPNET_WP.exe的主要任务是将请求交给一系列称为HTTP管道的托管对象。如果把ASP.NET ISAPI比做销售商,那么ASPNET_WP.exe就是生产商,而HTTP管道就是生产的流水线,负责流水线的小组就是HttpRuntime。生产商ASPNET_WP.exe会将订单(HTTP请求)交给HttpRuntime小组的工作人员ProcessRequest(HttpWorkerRequest wr),HttpRuntime根据内部的分工,最终由ProcessRequestInternal(HttpWorkerRequest wr)在流水线上进行生产。
向模块注册中添加 precondition 属性,并将其值设置为managedHandler。
此条件会导致仅在请求 ASP.NET 应用程序资源(例如 .aspx 文件或托管处理程序)时才调用该模块。该资源中不包括静态文件(例如 .htm 文件)。
其 configuration 节将类似于以下示例。
<configuration> <system.webServer> <modules> <add name="CustomModule" type="Samples.CustomModule" precondition="managedHandler" /> </modules> <defaultDocument> <files> <add value="Products.aspx" /> </files> </defaultDocument> </system.webServer> </configuration>
<system.webServer> <!--集成模式--> <modules> <add name="BaseHttpHandler" type="Frame.Core.BaseHttpHandler" /> </modules> <handlers> </system.webServer>
zhongkeMVC原理:自定义handler(必须实现IhttpModel,想用请求管道的19个事件就必须实现,init是最主要得方法)并且在web.config注册
通过web.config配置注册模块托管代码,截获每次请求到baseHandler,在此分析请求地址中的controller、action,然后反射调用相应的方法,通过VTempalte模板替换所有HTML中相应的值,最后返回给用户。
ps:baseHandler 在global之前
程序启动先根据web.config去创建baseHandler并且执行他的init方法,还有VT模板的一些初始化 方法,此时执行了三个方法
this.OnInit(EventArgs.Empty);
this.OnLoad(EventArgs.Empty);
this.OnRender(EventArgs.Empty);
然后才执行 global中的 Application_Start事件(Application_Start 和baseHandler中init只是程序启动时执行一次,每次请求的时候不再执行那两个方法)
每次回话开始的的时候先执行global中Session_Start然后执行正常的每次请求
每次请求 先执行Application_BeginRequest 然后是baseHandler中的那通过 IHttpHandler.ProcessRequest 调用那三个初始化方法
public class BaseHttpHandler : TemplatePageBase, IHttpModule, IRequiresSessionState
TemplatePageBase 是他的父类 所以先之心BaseHttpHandler 中的方法
2016-7-25
现在的理解 他这个框架没用注册任何时间 就是利用 第八个创建请求对象的的时候 就创建了httphandler 然后到11 12事件之间的时候执行里面的processrequest方法,根据分析地址去找控制器 去找html文件, 替换模板内容
一般情况下 称HttpModel为过滤器
global中有些方法是和管道中的时间对应的 不过是先执行自定义模块中管道中绑定的方法,然后在执行global中的 一一对应
processRequest调用管道19个事件 到第12个的时候 有一个hanler的processrequest的方法
一般处理程序和aspx页到12个都执行这个方法
一般处理程序:是程序员写的处理代码
aspx:是页面的整个生命周期
托管和非托管是什么意思?
托管代码 (managed code) :由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。 Unmanaged Code - 非托管代码 :在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged Code ,它是在公共语言运行库环境的外部,由操作系统直接执行的代码。
MVC怎么进入管道的
httpapplaction 创建之后会遍历创建所有module 包括 URLRoutingMdeule路由处理
遍历完URLRoutingMdeule 执行他的init方法,完成了请求管道中第七个事件的注册
通过反编译可以看到 URLRoutingMdeule 注册了第七个事件
遍历完 执行 processRequest 开始进入管道 到第七个事件的时候
执行注册的方法,根据路由数据创建MVChandler 实现了Ihttphanlder
到十一、十二个事件之间 执行 processrequest(去找控制器 、方法)
这个processrequest
asp.net:page_load一系列方法
MVC:去匹配控制器、方法
一般处理程序:程序员直接实现代码
一系列处理 到httpruntime 然后创建 httpcontext 并且对象池获取 Application
然后进入管道piplines
7/8事件之间 获取 httpHandler
MVC 生命周期
https://www.cnblogs.com/fzrain/p/3651693.html
HttpApplication的处理管道19个事件。
https://www.cnblogs.com/wolf-sun/p/5236185.html
HttpApplication对象是由Asp.net帮助我们创建的,它是asp.net中处理请求的重要对象。为了便于扩展,HttpApplication采用处理管道的方式进行处理,将处理的步骤分为多个步骤,每个步骤通过事件的形式暴露给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以定义一个请求的扩展过程。
对于HttpApplication,到ASP.NET 4.0,提供了19个标准事件。
1.BeginRequest:asp.net开始处理请求的第一个事件,表示处理的开始。
2.AuthenticateRequest:验证请求,一般用来取得请求的用户信息。
3.PostAuthenticateRequest:已经获取请求的用户信息。
4.AuthorizeRequest:授权,一般用来检查用户的请求是否获得权限。
5.PostAuthorizeRequest:用户请求已经获得授权。
6.ResolveRequestCache:获取以前处理缓存的处理结果,如果以前缓存过,那么,不用再进行请求的处理工作,直接返回缓存的结果。
7.PostResolveRequestCache:已经完成缓存的处理工作。
8.PostMapRequestHandler:已经根据用户的请求,创建了请求的处理器对象。
9.AcquireRequestState:取得请求的状态,一般用于session
10.PostAcquireRequestState:已经获得了session
11.PreRequestHandlerExecute:准备执行处理程序。
12.PostRequestHandlerExecute:已经执行了处理程序
13.ReleaseRequestState:释放请求的状态。
14.PostReleaseRequestState:已经释放了请求的状态。
15.UpdateRequestCache:更新缓存。
16.PostUpdateRequestCache:已经更新了缓存。
17.LogRequest:请求的日志操作
18.PostLogRequest:已经完成请求的日志操作。
19.EndRequest:本次请求处理完成。
ASP.NET MVC中的Global.asax文件
1.global.asax文件概述
global.asax这个文件包含全局应用程序事件的事件处理程序。它响应应用程序级别和会话级别事件的代码。
运行时, Global.asax 将被编译成一个动态生成的 .NET Framework 类,该类是从HttpApplication基类派生的。
因此在global.asax中的代码可以访问HttpApplication类中所有的public或者protected的成员
global.asax不被用户直接请求,但global.asax中的代码会被自动执行来响应特定的应用程序事件。
global.asax是可选的,而且在一个web项目中是唯一的,它应该处于网站的根目录。
2.一个请求的完整处理过程
以下过程由Internet Information Service(inetinfo.exe)(IIS)执行
1.客户端发出请求
2.验证请求
3.给请求授权
4.确定请求的缓存
5.获取缓存状态
6.在请求的处理程序执行前
7.http处理程序执行请求 (asp.net页面由aspnet_wp.exe执行)
8.在请求的处理程序执行后
9.释放请求状态
10.更新请求缓存
11.请求结束
3.global.asax中的事件
global.asax中的所有事件可以分成两种,一种是满足特定事件时才会被触发,一种是每次请求都会被按照顺序执行的事件。
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { //不是每次请求都调用 //在Web应用程序的生命周期里就执行一次 //在应用程序第一次启动和应用程序域创建事被调用 //适合处理应用程序范围的初始化代码 } void Application_End(object sender, EventArgs e) { //不是每次请求都调用 //在应用程序关闭时运行的代码,在最后一个HttpApplication销毁之后执行 //比如IIS重启,文件更新,进程回收导致应用程序转换到另一个应用程序域 } void Session_Start(object sender, EventArgs e) { //不是每次请求都调用 //会话开始时执行 } void Session_End(object sender, EventArgs e) { //不是每次请求都调用 //会话结束或过期时执行 //不管在代码中显式的清空Session或者Session超时自动过期,此方法都将被调用 } void Application_Init(object sender, EventArgs e) { //不是每次请求都调用 //在每一个HttpApplication实例初始化的时候执行 } void Application_Disposed(object sender, EventArgs e) { //不是每次请求都调用 //在应用程序被关闭一段时间之后,在.net垃圾回收器准备回收它占用的内存的时候被调用。 //在每一个HttpApplication实例被销毁之前执行 } void Application_Error(object sender, EventArgs e) { //不是每次请求都调用 //所有没有处理的错误都会导致这个方法的执行 } /*********************************************************************/ //每次请求都会按照顺序执行以下事件 /*********************************************************************/ void Application_BeginRequest(object sender, EventArgs e) { //每次请求时第一个出发的事件,这个方法第一个执行 } void Application_AuthenticateRequest(object sender, EventArgs e) { //在执行验证前发生,这是创建验证逻辑的起点 } void Application_AuthorizeRequest(object sender, EventArgs e) { //当安全模块已经验证了当前用户的授权时执行 } void Application_ResolveRequestCache(object sender, EventArgs e) { //当ASP.NET完成授权事件以使缓存模块从缓存中为请求提供服务时发生,从而跳过处理程序(页面或者是WebService)的执行。 //这样做可以改善网站的性能,这个事件还可以用来判断正文是不是从Cache中得到的。 } //------------------------------------------------------------------------ //在这个时候,请求将被转交给合适程序。例如:web窗体将被编译并完成实例化 //------------------------------------------------------------------------ void Application_AcquireRequestState(object sender, EventArgs e) { //读取了Session所需的特定信息并且在把这些信息填充到Session之前执行 } void Application_PreRequestHandlerExecute(object sender, EventArgs e) { //在合适的处理程序执行请求前调用 //这个时候,Session就可以用了 } //------------------------------------------------- //在这个时候,页面代码将会被执行,页面呈现为HTML //------------------------------------------------- void Application_PostRequestHandlerExecute(object sender, EventArgs e) { //当处理程序完成对请求的处理后被调用。 } void Application_ReleaseRequestState(object sender, EventArgs e) { //释放请求状态 } void Application_UpdateRequestCache(object sender, EventArgs e) { //为了后续的请求,更新响应缓存时被调用 } void Application_EndRequest(object sender, EventArgs e) { //EndRequest是在响应Request时最后一个触发的事件 //但在对象被释放或者从新建立以前,适合在这个时候清理代码 } void Application_PreSendRequestHeaders(object sender, EventArgs e) { //向客户端发送Http标头之前被调用 } void Application_PreSendRequestContent(object sender, EventArgs e) { //向客户端发送Http正文之前被调用 } }
原文: https://technet.microsoft.com/zh-cn/sysinternals/bb763179.aspx
https://www.cnblogs.com/lgxlsm/p/5573088.html