原文链接:http://aspnet.4guysfromrolla.com/articles/011404-1.aspx
作者:Scott Mitchell
简介
你是否仔细地想过当一个Asp.net Web页面请求到达服务器的时候,服务器端发生了什么?服务器是如何处理到来的请求的?发送给浏览器的HTML是怎么产生的?开发者可能会用什么机制去处理不同阶段的请求呢?这篇文章将对服务器如何处理Http请求进行详细的探讨。
步骤0:浏览器为ASP.NET Web页面产生一个Http请求
整个过程从为Asp.net Web页产生一个Http请求开始。例如,用户可能会在他的浏览器中输入这篇文章的URL地址,http://aspnet.4guysfromrolla.com/articles/011404.aspx。然后,浏览器会产生一个Http请求到4Guys的Web服务器,请求指定的文件/articles/011404-1.aspx。
步骤1:服务器接收Http请求
Web服务器唯一的任务就是接收到来的Http请求,返回一个带有请求资源的Http响应。4Guys Web服务器运行着Microsoft的Internet信息服务(IIS) Web服务器。请求到来时IIS要做的第一件事就是决定怎样处理这个请求,依据是请求的文件扩展名。例如,如果请求的文件扩展名为.asp,那么IIS会将这个请求让asp.dll处理。
有很多文件扩展名映射到Asp.net引擎。其中包括以下这些:
.aspx,Asp.net Web页面
.asmx,Asp.net Web服务
.config,Asp.net配置文件
.ashx,自定义Asp.net HttpHandler
.rem,远程资源
其他
在IIS管理界面,你能配置扩展名映射。例如,你能添加自定义的扩展名。也就是说,你能让Asp.net引擎处理.scott文件请求。
下面这张图阐明了Asp.net Web页请求的步骤0和1。当一个请求到达Web服务器时,它将被发送到适当的位置(也许是asp.dll,对ASP页面请求来说,也许是ASP.NET引擎,对ASP.NET请求来说)依据其请求文件的扩展名。
步骤2:检查ASP.NET引擎
http://aspnet.4guysfromrolla.com/articles/011404.aspx页的最初请求会到达IIS服务器,然后被发送到ASP.NET引擎,但是下一步发生了什么?ASP.NET引擎经常被提及到ASP.NET HTTP管道,因为进来的请求将通过一系列HTTP模块最终传到HTTP Handler。
HTTP模块是一些有权访问进来的请求的类。这些模块能检查进来的请求,作出一些影响内部流的决定。通过指定的HTTP模块后,请求到达某个Http Handler,它的工作是产生发送给浏览器的输出流。下图阐明了一个Asp.net请求流通过的管道。
Http管道默认包含一些预设的Http模块。这些模块包括:
OutputCache,处理返回或缓存页面的HTML输出流,如果需要
Session,装载基于请求的会话状态和Web.config文件里指定的会话方法
FormsAuthentication,基于窗体认证架构认证用户,如果需要
其他
实际上,你可以到Machine.config(位于$WINDOWS$\Microsoft.NET\Framework\$VERSION$\CONFIG)配置文件里寻找<httpModules>元素,你将看到一个详细的哪些模块被使用的清单。下面显示了默认的模块:
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
<add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule,
System.Web.Mobile, Version=1.0.5000.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</httpModules>
不同的Asp.net资源使用不同的Http Handler。在machine.config的<httpHandler>块详细的指明了这些默认使用的Http Handler。这个块的条目涉及一些类,要么是Http Handler本身,要么是Http Handler工厂。当Http Handler工厂被调用时它仅仅返回一个合适的Http Handler实例。
下面显示了在mechine.config中一部分<httpHandler>元素:
<add verb="*" path="*.vjsproj" type="System.Web.HttpForbiddenHandler" />
<add verb="*" path="*.java" type="System.Web.HttpForbiddenHandler" />
<add verb="*" path="*.jsl" type="System.Web.HttpForbiddenHandler" />
<add verb="*" path="trace.axd" type="System.Web.Handlers.TraceHandler" />
<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory" />
<add verb="*" path="*.ashx" type="System.Web.UI.SimpleHandlerFactory" />
</httpHandlers>
在Mansoor Ahmed Siddiqui的文章HTTP Handlers and HTTP Modules in ASP.NET你能看到一些关于Http模板和Handler非常棒的讨论。
步骤3:产生输出流
最后一步是使用适当的HttpHandler产生适当的输出流。然后,它反向地通过Http模板最终返回到IIS,IIS把它发送回初始请求的客户。(如果客户是浏览器,那么浏览器会接收到这个HTML然后解析显示它)
不同的HttpHandler,不同的输出流,让我们把焦点集中在特殊的HttpHandler - 呈现Asp.net Web页。折回初始的步骤,当一个Asp.net页(.aspx)请求到达IIS时,它被传送至Asp.net引擎。然后它通过一系列模板。该请求最终被传递到PageHandlerFactory,在machine.config的<httpHandler>块中我们有这样的映射:
<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory" />
</httpHandlers>
如果你是用Visual Studio.NET来创建Asp.net Web页的,你知道Web页是由两个分离的文件组成的:一个.aspx文件,其中包含HTML标记和Web控件;一个.aspx.vb或.aspx.cs文件,其中包含code-behind类(包括服务器端代码)。如果你没使用VS.NET,你可能使用服务器端<script>块来保持服务器端代码。不管你使用何种方法,当Asp.net Web页在改变HTML或Web控件内容之后首次被访问时,Asp.net引擎会创建一个源自System.Web.UI.Page类的类。然后这个被动态创建的类被编译。
Page类实现IHttpHandler,因此意味着它满足HttpHandler。接下来PageHandlerFactory检查是否已经存在被请求的Asp.net Web页面类的一个已编译版本。如果没有,它将动态创建这个类并编译它。然后,这个类的一些指定的方法被调用,从而产生页面全部的HTML标记。最后这些HTML标记返回给client。(你是否已经注意到当你对HTML或控件内容更改后去访问页面,会有一些延迟?这是因为Asp.net引擎得去重新创建和重新编译ASP.NET Web页的相应的类)
011404-1.aspx类在它能被调用而产生HTML之前首先应该被PageHandlerFactory创建并编译。页面呈递的过程 ,包括从被请求的Web页中获取HTML标记,已经超出本文范围,在Dino Esposito的The ASP.NET Page Object Model文章里有很好的讨论这方面的技术。
结论
这篇文章我们对Web服务器如何产生Asp.net Web页的过程进行了概括性的叙述。其中包括这些步骤,从client发出一个页面请求开始,最终被请求的Asp.net Web页面类产生需要呈递的HTML。在之间,请求通过IIS到ASP.NET引擎,然后通过一系列模板管道到达相应的HttpHandler。