.NEt专家博客!

【InsistYML】ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II

上一篇 / 下一篇  2008-07-24 14:19:28 / 个人分类:.net

二、ASP.NET Runtime Pipeline(续ASP.NET Http Runtime Pipeline - Part I)

现在我们真正进入ASP.NET管辖的范畴,下图基本上囊括整个处理过程涉及的对象,接下来我们一起来讨论这一系列的对象如何相互协作去处理Http Request,并最终生成我们所需的Http Response
yzG S#R uCbp0

ITPUB个人空间?L-i1H7pQ"\yg
HttpContext

上面我们介绍了ISAPI在调用ISAPIRuntime的时候将对应的ISAPI ECB Pointer作为参数传递给了ProcessRequest方法,这个ECB pointer可以看成是托管环境和非托管环境进行数据交换的唯一通道,Server VariableRequest Parameter通过它传入ASP.NET作为进一步处理的依据,ASP.NET最后生成的Response通过它传递给ISAPI,并进一步传递给IIS最终返回到Client端。

借助这个传进来的ECB Pointer,我们创建了一个ISAPIWorkerRequestISAPIWorkerRequest作为参数传入HttpRuntime.ProcessRequestNoDemand的调用。HttpRuntime.ProcessRequestNoDemand最终体现在调用ProcessRequestInternal。下面是真个方法的实现:ITPUB个人空间n OG7r3L;vcbz

&o;?f0Ld2f-?0

ProcessRequestInternal

 对象上面的代码没有必要深究,我们只需要了解大体的执行流程就可以了,下面这一段伪代码基本上体现整个执行过程:

HttpContext context = new HttpContext(wr, false);ITPUB个人空间,?$FA0u~
 IHttpHandler applicationInstance 
= HttpApplicationFactory.GetApplicationInstance(context);ITPUB个人空间!ws8P;?5D&k

首先通过创建的ISAPIWorkerRequest创建按一个HttpContext对象,随后通过HttpApplicationFactory.GetApplicationInstance创建一个IHttpHandler对象(一般情况下就是一个HttpApplication对象)。

正如他的名字体现的,HttpContext体现当前Request的上下文信息,它的生命周期知道整个Request处理结束或者处理超时。通过HttpContext对象我们可以访问属于当前Request的一系列常用的对象:ServerSessionCacheApplicationRequestResponseTraceUserProfile等等。此外我们可以认为将一些数据放在Items属性中作为状态管理的一种方式,不过这种状态管理和其他一些常用的方式,比如SessionCacheApplicationCookie等,具有根本性的不同之处是其生命周期仅仅维持在当前RequestContext中。

2.            HttpApplication

就像其名称体现的一样,HttpApplication基本上可以看成是真个ASP.NET Application的体现。HttpApplication和置于虚拟根目录的Gloabal.asax对应。通过HttpApplicationFactory.GetApplicationInstance创建一个基于Gloabal.asaxHttpApplication对象。在HttpApplicationFactory.GetApplicationInstance方法返回创建的HttpApplication对象之前,会调用一个名为InitInternal的内部方法,该方法会做一些列的初始化的操作,在这些初始化操作中,最典型的一个初始化方法为InitModules(),该方法的主要的目的就是查看Config中注册的所有HttpModule,并根据配置信息加载相应的Assembly,通过Reflection创建对应的HttpModule,并将这些Module加到HttpApplication_moduleCollectionFiled中。

HttpApplication本身并包含对Request的任何处理,他的工作方式是通过在不同阶段出发不同Event来调用我们注册的Event Hander

下面列出了HttpApplication所有的Event,并按照触发的时间先后顺序排列:

  • BeginRequest
  • AuthenticateRequest & Post AuthenticateRequest
  • AuthorizeRequest & Post AuthorizeRequest
  • ResolveRequestCache & Post ResolveRequestCache
  • PostMapRequestHandler:
  • AcquireRequestState & AcquireRequestState:
  • PreRequestHandlerExecute & Post RequestHandlerExecute:
  • ReleaseRequestState & Post ReleaseRequestState
  • UpdateRequestCache & PostUpdateRequestCache
  • EndRequest:

ASP.NET Application, AppDomain and HttpApplication

对于一个ASP.NET Application来说,一个Application和一个虚拟目录相对应,那么是不是一个Application对应着一个AppDomain呢?一个Application是否就唯一对应一个Httpapplication对象呢?答案是否定的。

我们首先来看看ApplicationHttpApplication的关系,虽然我们对一个ApplicationRequest最终都由一个HttpApplication对象来承载。但不能说一个Application就唯一对应一个固定的HttpApplication对象。原因很简单,ASP.NET天生具有多线程的特性,需要通过相应不同的Client的访问,如果我们只用一个HttpApplication来处理这些并发的请求,会对Responsibility造成严重的影响,通过考虑到Performance的问题,ASP.NETHttpApplication的使用采用Pool的机制:当Request到达,ASP.NET会现在HttpApplication Pool中查找未被使用的HttpApplication对象,如果没有,则创建之,否则从Pool直接提取。对于Request处理完成的HttpApplication对象,不会马上销毁,而是把它放回到Pool中供下一个Request使用。

对于ApplicationAppDomain的关系,可能你会说一个Application肯定只用运行在一个AppDomain之中。在一般情况下这句话无可厚非,但是这却忽略了一种特殊的场景:在当前Application正在处理Request的时候,我们把web.config以及其他一些相关文件修改了,而且这种改变是可以马上被ASP.NET检测到的,为了使我们的变动能够及时生效,对于改动后的第一个RequestASP.NET会为期创建一个新的AppDomain,而对于原来的AppDomain,也许还在处理修改前的Request,所有原来的Appdomain会持续到将原来的Request处理结束之后,所以对于一个Application,可能出现多个AppDomain并存的现象。

3.            HttpModule

我们上面提到HttpApplication就是一个ASP.NET Application的体现,HttpApplication本身并不提供对Request的处理功能,而是通过在不同阶段出发不同的Event。我们能做的只能是根据我们具体的需求将我们的功能代码作为Event Handler注册到需要的HttpApplication Event上面。注册这些Event Handler,我们首先想到的肯定就直接在HttpApplication对应的Global.asax中定义我们的EventHandler好了。这是最直接的办法,而且Global.asax提供一个简洁的方式是我们的实现显得简单:不需要向一般注册Event一样将Delegate添加到对应的Event上面,而是直接通过方法名称和对应的Event匹配的方式直接将对应的方法作为相关的Event Handler。比如Application_ AcquireRequestState就是AcquireRequestState Event handler

但是这种方式在很多情况下却达不到我们的要求,更多地,我们需要的是一种Plug-in的实现方式:我们在外部定义一些Request Processing的功能,需要直接运用到我们的Application之中。通过使用HttpModule封装这些功能模块,并将其注册到我们的Application的发式可以很简单的实现这种功能。

HttpModule实现了System.Web.IHttpModule interface,该Interface很简单,仅仅有两个成员:

[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
a7nb0} OO0
public interface IHttpModule
)R#CzKc2d1p0
{ITPUB个人空间\w'{7]CntMS
    
// Methods
(yrm*P0['z0
    void Dispose();
-^qN @2?N0    
void Init(HttpApplication context);ITPUB个人空间9O }^6i5W{`
}
ITPUB个人空间*L5Ns8wVR)}-\9P

我们只要在Init方法中注册相应的HttpApplication Event Handler就可以了:ITPUB个人空间}V GR$VJ

public class BasicAuthCustomModule : IHttpModule
.`%~X:`:s n/O'ag0

i _z'z GE0      
public void Init(HttpApplication application)ITPUB个人空间-|H/tU Du
      
{
!{r^^*Y k1Dn7PW c0            application.AuthenticateRequest 
+= 
Qe f;l9{*H0                
new EventHandler(this.OnAuthenticateRequest);
){p&s1YoX0cLr0      }
ITPUB个人空间#Mj!H/N*ik
      
public void Dispose() { }ITPUB个人空间*QBS'E QG
 
"E mv \ l2k0      
public void OnAuthenticateRequest(object source, EventArgs eventArgs)
XNH'la2w0      
{ITPUB个人空间yWz6{?.jD JO

b.Q3\?&?8o"Z#IPw r'M0      }
 ITPUB个人空间%U?&q&N^iHY|k*eM
}

2Vuc:S6HG2u0

所有的HttpModulemachine.config或者Web.confighttpModules Section定义,下面是Machine.config定义的所有httpModule

 

<httpModules>ITPUB个人空间ZU5f)v+EL+Z
            
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
9xZr _,~H/V0            
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
-mv)} p2J(j eH^H@0            
<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />ITPUB个人空间5w ^ M?-oNPTdkrq
            
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />ITPUB个人空间)_ x7LeP@'KI
            
<add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
0I~ z0Q0j0{ B)_9D0            
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
3g1JS!LiX6T0            
<add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
6@|9BGX*t0            
<add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=1.0.5000.0, 

TAG: 微软

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar