DotText源码学习——ASP.NET的工作机制

简介:

——本文是《项目驱动学习——DotText源码学习》系列的第一篇文章,在这之后会持续发表相关的文章。

概论

在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使我们更好的理解。ASP.NET是Web服务器(IIS)的 ISAPI(Internet Server API)扩展。当IIS接收到客户端浏览器发来的请求后,它根据请求的文件类型确定由哪个ISAPI扩展来处理该请求,并将请求转发给ASP.NET(如 果是ASP.NET处理的相应文件类型的话,如*.aspx、*.asmx、*.ashx)。ASP.NET应用首先进行初始化,并装载配置模块,然后经 过一系列步骤来完成对客户端请求的响应。

下面按以下步骤来解析ASP.NET的工作机制:

  • Step1:用户从浏览器中请求网页(.aspx)
  • Step2:ASP.NET接收到对应用程序的第一个请求
  • Step3:为每个请求创建ASP.NET核心对象
  • Step4:将HttpApplication对象分配给请求
  • Step5:由HttpApplication管线处理请求

Step1、用户从浏览器中请求网页(.aspx)

当IIS收到请求后,会对所请求文件的扩展名进行检查,确定应该由哪个ISAPI扩展来处理该请求,然后将该请求传递给合适的ISAPI扩展,也就是说IIS将该请求传给ASP.NET。

说明:

1、ASP.NET即是IIS的ISAPI扩展,并且ASP.NET处理已映射到它的文件扩展名,如.aspx、.ascx、.ashx和.asmx

2、ISAPI(Internet Server API)服务器扩展是可以被HTTP服务器加载和调用的DLL。Internet服务器扩展也称为Internet服务器应用程序(ISA),用于增强符 合Internet服务器API(ISAPI)的服务器的功能。ISA 通过浏览器应用程序调用,并且将相似的功能提供给通用网关接口 (CGI) 应用程序。想了解更多

IIS是如何将请求传给ASP.NET的呢,或者说他们是怎么通信的呢?其实,IIS捕获的任何请求经过检查分析,然后映射到一个外部模块进行真正的处理。而负责处理输入的ASP.NET请求的外部模块,是一个名为aspnet_isapi的动态链接库(DLL)——aspnet_isapi.dll。该模块并不是一个普通的DLL,而是一个ISAPI模块。ISAPI模块是实现了一种特殊协议的DLL,能够与IIS可执行文件通信。

下面以IIS6的进程模型为例,说明这个过程(注意:不同的IIS版本这个过程是有差异的)。

IIS 6.0进程模型,也称为工作进程隔离模式(worker process isolation mode),是以应用程序池的 概念为中心的。IIS6.0总会保持一个单独的工作进程——应用程序池。所有的处理都发生在这个进程里,包括ISAPI DLL的执行。应用程序池是一组共享相同的工作进程副本的Web应用程序,从而将Web服务器的核心部分与可能无法正常工作的应用程序相分离。我们可以用 一组不同的属性来配置每个应用程序池及其工作进程副本。

在默认的IIS 6.0进程模型下运行时,ASP.NET应用程序使用一个通用的、与ASP.NET无关的(ASP.NET-agnostic)工作进程——这也是服务Web服务器托管的所有应用程序的工作进程,该程序名为w3wp.exe。在IIS6.0里,ISAPI扩展运行在应用程序池的工作进程里。而.NET运行时也运行在这个进程里,所有ISAPI扩展和.NET运行时的通信时发生在进程内的,这就使得性能更高。

分配给同一个应用程序池的所有Web应用程序共享该可执行程序的一个副本。IIS 6.0构架的另一个关键组件是名为http.sys的内核模式设备驱动程序。该驱动程序是负责捕获并服务任何输入请求的HTTP监听程序。

当一个请求到达时,http.sys把它传递到被调用应用程序所属的应用程序池管理的队列。每个应用程序池有一个队列。w3wp.exe工作 进程装入aspnet_isapi.dll;接着该ISAPI扩展装入公共语言运行库(common language runtime,简称CLR),启动ASP.NET运行库管道来处理请求。如果IIS 6.0进程模型正在使用,内置的ASP.NET工作进程将被禁用。工作进程使用http.sys获取请求,并把响应发送给客户端。

就这样一个请求通过IIS6.0被转到ASP.NET进行处理。下面用一个图来形象描述。

Step2、ASP.NET接收到对应用程序的第一个请求

当ASP.NET接收到对应用程序中任何资源的第一个请求时,应用程序管理器(ApplicactionManager)就会创建一个应用程序域;在应用程序域中,将创建宿主环境(HostingEnviroment类的实例),它提供对有关应用程序的信息的访问。

说明:

1、应用程序域(AppDomain)为全局变量提供应用程序隔离,在其中可以加载和执行托管代码程序集,并允许单独卸载每个应用程序,但不允许卸载单个程序集只能通过卸载应用程序域来卸载程序集。

2、HostingEnvironment类,在托管应用程序的应用程序域(AppDomain)内向托管应用程序提供应用程序管理功能应用程序服务

如下图所示:

 

应用程序域(AppDomain)是怎么创建的呢?其实是这么回事:从Step1知道接收到请求后IIS6.0的w3wp.exe工 作进程将装入aspnet_isapi.dll,接着该ISAPI扩展装入CLR,启动ASP.NET运行库管道来处理请求。在 aspnet_isapi.dll理是通过调用ISAPIRuntime派生类的实例进入.NET运行时的,这是因为IISAPIRuntime接口担当 着来自于ISAPI扩展的非托管代码和托管代码之间的桥梁。

一旦运行时存在了,非托管代码就可以为指定的虚拟目录请求一个ISAPIRuntime对象的实例(如果这个实例还不存在)。每一个虚拟目录都会拥有一个AppDomain,在ISAPIRuntime存在的AppDomain里,它将引导一个单独的程序启动。为了创建ISAPIRuntime的实例,当指定虚拟目录的第一个请求到达时,System.Web.Hosting.AppDomainFactory.Create()方法将被调用(点此查看在MSDN中关于System.Web.Hosting.AppDomainFactory.Create()方法的描述)。这 将会启动程序的引导过程。这个方法接收的参数为:类型,模块名以及应用程序的虚拟路径,这些都将被ASP.NET用于创建AppDomain,接着会启动 指定虚拟目录的ASP.NET程序。HttpRuntime的根对象将会在一个新的AppDomain里创建。每一个虚拟目录或者ASP.NET程序将寄 宿在属于自己的AppDomain里。它们仅仅在有请求到达时启动。ISAPI扩展管理这些HttpRuntime对象的实例,然后基于请求的虚拟路径, 把请求路由到正确的应用程序里。

Step3、为每个请求创建ASP.NET核心对象

创建应用程序域并实例化了宿主环境之后,ASP.NET将创建并初始化核心对象(如HttpContext、HttpRequest和 HttpRespone)。HttpContext类包含特定于当前应用程序请求的对象,如HttpRequest和HttpRespone对象。 HttpRequest对象包含有关当前请求的信息,包括Cookie和浏览器信息。HttpRespone对象包含发送到客户端的响应,包括所有呈现的 输出和Cookie。这些工作都是在ISAPIRuntime.ProcessRequest()方法里执行的。详细的了解HttpContext点此查看MSDN。

其实,一旦运行时启动并运行起来,ISAPI扩展就可以调用ISAPIRuntime.ProcessRequest()方法了,而这个方法就是进入ASP.NET通道真正的登录点。经过Step2后,请求它将被路由到ISAPIRuntime.ProcessRequest()方法里。这个方法会接着调用HttpRuntime.ProcessRequest,在这个方法里,做了几件重要的事情:

  • 为请求创建了一个新的HttpContext实例
  • 获取一个HttpApplication实例
  • 调用HttpApplication.Init()初始化管道事件
  • Init()触发HttpApplication.ResumeProcessing(),启动ASP.NET管道处理。

Step4、将HttpApplication对象分配给请求

初始化所有核心应用程序对象之后,将通过创建HtppApplication类的实例启动应用程序。如果应用程序具有Global.asax文件, 则ASP.NET会创建Global.asax类(从HttpApplication类派生)的一个实例,并使用该派生类表示应用程序。同 时,ASP.NET将创建所有已配置的模块(如状态管理模块、安全管理模块),在创建完所有已配置的模块后,将调用HttpApplication类的 Init方法。

Global.asax里的事件处理器会自动映射到对应的事件,也可以映射到额外添加的HttPModules,这些HttPModules本质上 是HttpApplication已发布事件的一种扩展。我们可以自己定一些HttpModules和HttpHandlers,然后通过在 web.config里注册,HttPModules和HttpHandlers可以被动态的加载,并且可以添加到事件链条上。HttPModules实 际上就是事件处理器,它可以钩住指定HttpApplication的事件。而HttpHandlers就是一个端点,它可以被调用处理“应用程序级的请 求处理”。HttPModules和HttpHandlers将被加载,然后添加到调用链上作为HttpApplication.Init()方法调用的 一部分。

如下图所示:

 

说明:每一个请求都将被路由到一个HttpApplication对象。HttpApplicationFactory类会为你的ASP.NET程 序创建一个HttpApplication对象池,它负责加载程序和给每一个到来的请求分发HttpApplication的引用(由Step2知道这些是在ISAPIRuntime.ProcessRequest()方法中调用HttpRuntime.ProcessRequest()完成的)。

 

Step5、由HttpApplication管线处理请求

在该阶段由HttpApplication类执行一系列事件;并根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现了IHttpHandler的类来对请求处理(即由一些HttpHandlers处理)。

HttpApplication主要用作HTTP管道的事件控制器,因此,它的接口主要有事件组成,这些事件包括:

  • BeginRequest
  • AuthenticateRequest
  • AuthorizeRequest
  • ResolveRequestCache
  • AquireRequestState
  • PreRequestHandlerExecute
  • …Handler Execution…
  • PostRequestHandlerExecute
  • ReleaseRequestState
  • UpdateRequestCache
  • EndRequest

ASP.NET管道一旦启动,HttpApplication将逐一触发事件,如上所述的事件。每一个事件都将被触发,如果事件绑定了事件处理器, 那么这些事件处理器将被调用,执行它们的任务。这个过程的主要目的是通过调用HttpHandler处理指定的请求。对于ASP.NET请求而 言,HttpHandler是处理请求机制的核心,在这里任意的应用程序级的代码被执行。

如果该请求针对从Page类派生的对象(页),并且需要对该页进行编译,则ASP.NET会在创建该页的实例之前对其进行编译,在装载后用该实例来处理这个请求,处理完后通过HttpRespone输出,最后释放该实例。

相关文章
|
6月前
|
开发框架 前端开发 JavaScript
盘点72个ASP.NET Core源码Net爱好者不容错过
盘点72个ASP.NET Core源码Net爱好者不容错过
162 0
|
6月前
|
开发框架 .NET
ASP.NET Core NET7 增加session的方法
ASP.NET Core NET7 增加session的方法
88 0
|
存储 开发框架 前端开发
asp.net与asp.net优缺点及示例
asp.net与asp.net优缺点及示例
|
3月前
|
开发框架 JSON .NET
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
|
3月前
|
开发框架 .NET 数据库连接
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
|
6月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
|
6月前
|
SQL 开发框架 JavaScript
分享33个ASP.NET电子商务源码和40个ASP.NET控件组件源码,总有一款适合您
分享33个ASP.NET电子商务源码和40个ASP.NET控件组件源码,总有一款适合您
83 0
|
6月前
|
存储 开发框架 .NET
Asp.net就业课之Ado.net第一次课
Asp.net就业课之Ado.net第一次课
42 0
|
存储 开发框架 .NET
ASP.NET学生管理系统(.NET毕业设计)
ASP.NET学生管理系统(.NET毕业设计)
157 0
|
开发框架 前端开发 JavaScript
ASP .Net Core 中间件的使用(一):搭建静态文件服务器/访问指定文件
ASP .Net Core 中间件的使用(一):搭建静态文件服务器/访问指定文件