原文 http://www.cnblogs.com/DotNetEnjoy/archive/2013/04/15/3022672.html
asp.net的请求处理模型已经讲完几个星期了,但一直没有时间整理,一来是因为知识点确实繁杂,难以整理,二来了解得也不够清晰,存在一些误区。今天有空写下这篇博文,希望大家指正其中的不足,以便能加深对请求响应的理解。
根据自己理解和老师讲课的内容,花了一张图
1、浏览器实际上是一个Socket客户端,它向服务器发送请求报文
2、请求报文被封装为http请求,通过socket发送到IIS服务器
3、内核模式包含一个Http.SYS文件,它用来监听端口,接收请求后将其发送到用户模式。
4、用户模式中IIS将请求发送到w3svc.exe进程中,
5、w3svc.exe将请求发到inetinfo.exe中。
6、inetinfo.exe截获请求后,根据资源映射信息,将请求的资源分配到特定的处理程序模块。
8、如果请求的是静态资源(img、html等),则由IIS将本地文件内容输出到浏览器。
7、如果是动态资源,则告诉w3svc.exe应该把请求传到对应的扩展模块中,如aspx请求会分配到aspnet_isapi.dll扩展程序中
9、 aspnet_isapi.dll是一个扩展程序,实现了IIS内部的一些API,也是一种请求过滤的插件。它的作用是1.负责启动托管环境。2.初始化 托管环境。3.将请求分发给托管环境。也就是说,它负责启动aspnet Runtime创建aspnet运行环境,将请求交给ISAPIRuntime的PR方法。
10、aspnet_isapi.dll会将请求发到w3wp.exe中处理
在IIS中,工作进程(w3wp.exe)运行着ASP.NET应用程序,管理并响应所有的请求,ASP.NET所有的功能都运行在工作进程下,当请求到来时,工作进程会生成Request和Response相关的信息。简而言之,工作进程就是ASP.NET程序的心脏。
11、 然后在扩展模块中调用ISAPIRuntime(ISAPIRuntime是进入.NET托管环境的入口)的ProcessRequest方法,,该方法 要求传入一个ecb句柄(ecb句柄指向请求报文的内存地址),将其创建为一个HttpWorkRequest对象。HttpWorkRequest只是 对请求进行简单的封装。
12、将HttpWorkRequest对象放到HttpRuntime的ProcessRequest方法中,返回一个HttpContext上下文对象。
13、HttpContext上下文对象包含HttpRequest请求报文和HttpResponse响应报文
14、根据HttpApplication获 得一个HttpApplication对象的实例,获取实例的时候,先去Application池中去找是否有空闲的HttpApplication对 象,如果有则直接返回一个对象,不存在的话就就先编译globle文件生成一个HttpApplication的派生类,通过反射创建一个 HttpApplication实例并返回。并开始处理用户的请求。
15、用户的请求是通过触发HttpApplication的19个事件23个步骤进行处理的。如果是一般处理程序(.ashx),那么执行完管道中的事件后按照原路进行返回。如果是aspx页面那么就开始走页面的生命周期了。
16、HttpApplication对HttpContext处理完成后,通过Socket返回响应报文
17、浏览器接收响应报文(解析Html并渲染Html标签、CSS、JS)
下面是对管道的一些理解,图是找来的,原图有一些错误,已修正
页面的生命周期发生在第11至12个事件。执行步骤如下
1、创建页面控件树BuilderControlTree:将C#创建控件的代码封装到FrameworkInitliaze() 方法中,在方法内部将aspx所有控件new一个实例,然后构造树结构
2、判断是否回发,如果ViewState为null,则不是回发,IsPostBack为false,如果有值,则为True。
3、初始化包括三个阶段:PreInit()预初始化:Init()初始化:InitComplete()初始化完成.做的主要操作是创建控件ID,然后将所有控件的Page属性指向当前页面
4、加载ViewState处理回发数据,将数据放到控件中,将需要触发事件的控件放到一个集合里面去。
5、预加载PreLoad,加载Load(Page_Load()),其实就是执行Page_Load里的代码
6、第二次处理回发数据
7、触发改变的事件和点击事件
8、加载完成
9、预渲染OnPreRender:最后改变页面状态,保存对控件状态做的更改
10、保存页面状态SavaViewState:自动将控件的ViewState属性保持到字符串对象中,并放到隐藏域中发送到客户端
11、渲染Render:
页面生命周期结束后,继续管道之后的事件。
了解页面的生命周期,有助于我们在适当的事件中放入逻辑,而不是一味的将逻辑放到页面加载Page_Load中。以下是从网上截的一张图。