ASP.NET应用程序与页面生命周期

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET应用程序与页面生命周期相关的知识,希望对你有一定的参考价值。

 在本文中,我们将了解不同的事件,ASP.NET 应用程序的生命周期以浏览器向 Web 服务器(对于 ASP.NET 应用程序,通常为 IIS)发送请求为起点,直至将请求结果返回至浏览器结束。在这个过程中,首先我们需要了解ASP.NET请求的2个大致的步骤。其次我们将详细了解 ‘httphandler ‘,‘ httpmodule和 asp.net 页面对象(Page)中不同的事件的执行顺序,逻辑。

二个步骤的过程:asp.net请求处理,2步的过程如下所示,用户发送一个请求到IIS 服务器:

1、asp.net创建一个运行时,可以处理请求。换句话说,它创建应用程序对象,请求,响应和上下文对象处理请求。

2、运行时一旦被创建,请求处理,通过一系列的事件处理模块,Handler处理和页面对象。简称MHPM (Module, handler, page and Module event)。

技术分享

ASP.NET 应用程序生命周期的各个阶段:

步骤1:用户从 Web 服务器请求应用程序资源 ASP.NET 应用程序的生命周期以浏览器向 Web 服务器(对于 ASP.NET 应用程序,通常为 IIS)发送请求为起点。ASP.NET 是 Web 服务器下的 ISAPI 扩展。Web 服务器接收到请求时,会对所请求的文件的文件扩展名进行检查,确定应由哪个 ISAPI 扩展处理该请求,然后将该请求传递给合适的 ISAPI 扩展。ASP.NET 处理已映射到其上的文件扩展名,如 .aspx、.ascx、.ashx 和 .asmx。

步骤2:ASP.NET 接收对应用程序的第一个请求 当 ASP.NET 接收到对应用程序中任何资源的第一个请求时,名为 ApplicationManager 的类会创建一个应用程序域。应用程序域为全局变量提供应用程序隔离,并允许单独卸载每个应用程序。在应用程序域中,将为名为 HostingEnvironment 的类创建一个实例,该实例提供对有关应用程序的信息(如存储该应用程序的文件夹的名称)的访问。

技术分享

步骤3:为每个请求创建 ASP.NET 核心对象 创建了应用程序域并对 HostingEnvironment 对象进行了实例化之后,ASP.NET 将创建并初始化核心对象,如 HttpContextHttpRequest 和 HttpResponseHttpContext类包含特定于当前应用程序请求的对象,如 HttpRequest 和 HttpResponse 对象。HttpRequest 对象包含有关当前请求的信息,包括 Cookie 和浏览器信息。HttpResponse 对象包含发送到客户端的响应,包括所有呈现的输出和 Cookie。

 步骤4:将 HttpApplication 对象分配给请求初始化所有核心应用程序对象之后,将通过创建 HttpApplication 类的实例启动应用程序。如果应用程序具有 Global.asax 文件,则 ASP.NET 会创建 Global.asax 类(从HttpApplication 类派生)的一个实例,并使用该派生类表示应用程序

第一次在应用程序中请求 ASP.NET 页或进程时,将创建 HttpApplication 的一个新实例。不过,为了尽可能提高性能,可对多个请求重复使用 HttpApplication 实例。

技术分享

步骤5: 由 HttpApplication 管线处理请求 MHPM (Module, handler, page and Module event)

技术分享

技术分享

使用MHPM (Module, handler, page and Module event) 事件处理请求 
一旦 HttpApplication对象创建,在处理该请求时将由 HttpApplication 类执行。我们来了解下HttpModule HttpHandlers。

1、如果你想通过*.aspx,*.html文件来处理程序逻辑,那么你需要使用HttpHandler,换句话说,httphandler是一个扩展的处理器。

技术分享

2、如果你想使用ASP.NET管道来处理程序逻辑,你需要使用HttpModule 换句话说,httpmodule是一个事件处理器。

技术分享

如何处理请求。mhpm有4个重要的步骤:

步骤1(M: HttpModule):客户端开始请求处理。在asp.net引擎和httpmodule中的事件可以用来处理用户自己定义的逻辑。有6个重要的事件,你可以在你的页面对象被创建之前调用 Begin Requestauthenticaterequestauthorizerequestresolverequestcacheacquirerequeststateprerequesthandlerexecute

 

步骤2(H: ‘HttpHandler’):一旦上述6个事件被执行完,asp.net引擎调用processrequest事件,如果已实现httphandler在您的项目。

 

步骤3(P: ASP.NET page):一旦httphandler执行,asp.net页面对象被创建。而asp.net页面对象被创建,Page对象的事件将被调用,这可以帮助在页面中定制自定义逻辑的处理。有6个重要的事件,InitLoad,validateeventrender ,unload 简称 SILVER   S – Start (does not signify anything as such just forms the word) , I – (Init) , L (Load) , V (Validate), E (Event) and R (Render)。

步骤4(M: HttpModule):一旦页面对象执行完从内存中卸载,httpmodule提供网页执行事件可以用来注入自定义处理逻辑。有4个重要的后处理事件postrequesthandlerexecutereleaserequeststateupdaterequestcacheendrequest

技术分享

 事件详细介绍:

 
部分 Event事件 Description描述
HttpModule BeginRequest 在 ASP.NET 响应请求时作为 HTTP 执行管线链中的第一个事件发生。BeginRequest 事件发出信号表示创建任何给定的新请求。此事件始终被引发,并且始终是请求处理期间发生的第一个事件。
HttpModule AuthenticateRequest 当安全模块已建立用户标识时发生。AuthenticateRequest 事件发出信号表示配置的身份验证机制已对当前请求进行了身份验证。
HttpModule AuthorizeRequest 安全模块已验证用户授权时发生。AuthorizeRequest 事件发出信号表示 ASP.NET 已对当前请求进行了授权。
HttpModule ResolveRequestCache 在 ASP.NET 完成授权事件,缓存模块从缓存中为请求提供服务后发生,从而绕过事件处理程序(例如某个页或 XML Web services)的执行。
HttpModule AcquireRequestState 当 ASP.NET 获取与当前请求关联的当前状态(如会话状态)时发生。AcquireRequestState 事件在创建了事件处理程序之后引发。
HttpModule PreRequestHandlerExecute 恰好在 ASP.NET 开始执行事件处理程序(例如,某页或某个 XML Web services)前发生。
HttpHandler ProcessRequest Httphandler逻辑被执行。 在本节中,我们会写需要将每页扩展执行的逻辑。
Page Init

OnInit 方法执行创建 Page 实例所需的初始化和设置步骤。在页生命周期的此阶段中,页中声明的服务器控件都已初始化为默认状态;但每个控件的视图状态尚未填充。在 Page_Init 阶段中,页中的控件不能访问该页的其他服务器控件,无论其他控件是子控件还是父控件。不一定会创建其他服务器控件,也不一定能够访问它们

Page Load ASP.NET控件完成加载,你写的UI操作逻辑或任何其他逻辑在这里。
Page Validate 如果你有你的页面上有验证逻辑,这里检查是否符合验证。
Page Render 将页面最终的输出发送到浏览器,如果你想做出一些最终的HTML的变化,这是输出到浏览器,你可以在这里输入你的HTML的逻辑。
Page Unload 页面对象从内存中卸载。
HttpModule PostRequestHandlerExecute 在 ASP.NET 事件处理程序(例如,某页或某个 XML Web service)执行完毕时发生。
HttpModule ReleaserequestState 在 ASP.NET 执行完所有请求事件处理程序后发生。该事件将使状态模块保存当前状态数据。引发ReleaseRequestState 事件以后,应用程序以该请求结束,并发出 ASP.NET 信号以存储该请求状态。
HttpModule UpdateRequestCache Before you end, if you want to update your cache.结束之前,如果您想更新您的高速缓存。
HttpModule EndRequest 当 ASP.NET 执行完事件处理程序,使缓存模块存储用于为后续请求提供服务的响应时发生。

 

演示代码:

在这段代码中,我们创建HttpModule 和Httphandler  添加所有请求响应的事件, 下面用 HttpModule Httphandler  跟踪所有活动,并把它添加到一个全局性的集合变量中。 

技术分享
 public class clsHttpModule : IHttpModule
     {
         private HttpApplication httpApp;
         public static ArrayList objArrayList = new ArrayList();
         public clsHttpModule()
         { 
         }
  
         public void Dispose()
         { 
         }
 
         public void Init(HttpApplication context)
         {
             this.httpApp = context;
             httpApp.Context.Response.Clear();
             objArrayList.Clear();
             objArrayList.Add("httpModule:Init");
             httpApp.AuthenticateRequest += new EventHandler(OnAuthentication);
             httpApp.AuthorizeRequest += new EventHandler(OnAuthorization);
             httpApp.BeginRequest += new EventHandler(OnBeginrequest);
             httpApp.EndRequest += new EventHandler(OnEndRequest);
             httpApp.ResolveRequestCache += new EventHandler(OnResolveRequestCache);
             httpApp.AcquireRequestState += new EventHandler(OnAcquireRequestState);
             httpApp.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
             httpApp.PostRequestHandlerExecute += new EventHandler(OnPostRequestHandlerExecute);
             httpApp.ReleaseRequestState += new EventHandler(OnReleaseRequestState);
             httpApp.UpdateRequestCache += new EventHandler(OnUpdateRequestCache);
         }

         void OnUpdateRequestCache(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:OnUpdateRequestCache");
         }

         void OnReleaseRequestState(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:OnReleaseRequestState");
         }

         void OnPostRequestHandlerExecute(object sender, EventArgs a)
         {
            objArrayList.Add("httpModule:OnPostRequestHandlerExecute");
         }

         void OnPreRequestHandlerExecute(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:OnPreRequestHandlerExecute");
         }

         void OnAcquireRequestState(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:OnAcquireRequestState");
         }

         void OnResolveRequestCache(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:OnResolveRequestCache");
         }

         void OnAuthorization(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:OnAuthorization");
         }

         void OnAuthentication(object sender, EventArgs a)
         {
 
             objArrayList.Add("httpModule:AuthenticateRequest");
         }

         void OnBeginrequest(object sender, EventArgs a)
         {
 
             objArrayList.Add("httpModule:BeginRequest");
         }

         void OnEndRequest(object sender, EventArgs a)
         {
             objArrayList.Add("httpModule:EndRequest");
             objArrayList.Add("<hr>");
             foreach (string str in objArrayList)
             {
                 httpApp.Context.Response.Write(str + "<br>");
             }
         }
     }
View Code

以下代码片段是跟踪 HttpHandler 的ProcessRequest ‘事件‘ :

技术分享
 public class clsHttpHandler : IHttpHandler
     {
         public bool IsReusable
         {
             get { return true; }
         }
 
         public void ProcessRequest(HttpContext context)
         {
             clsHttpModule.objArrayList.Add("HttpHandler:ProcessRequest");
             context.Response.Redirect("~/Default.aspx");
         }
     }
View Code

页面Page事件:

技术分享
  public partial class _Default : System.Web.UI.Page
     {
         protected void Page_init(object sender, EventArgs e)
         {
             clsHttpModule.objArrayList.Add("Page:Init");
         }

         protected void Page_Load(object sender, EventArgs e)
         {
             clsHttpModule.objArrayList.Add("Page:Load");
         }

         public override void Validate()
         {
             clsHttpModule.objArrayList.Add("Page:Validate");
         }

         protected void Button1_Click(object sender, EventArgs e)
         {
             clsHttpModule.objArrayList.Add("Page:Event");
         }

         protected override void Render(HtmlTextWriter output)
         {
             clsHttpModule.objArrayList.Add("Page:Render");
             base.Render(output);
         }

         protected void Page_Unload(object sender, EventArgs e)
         {
             clsHttpModule.objArrayList.Add("Page:UnLoad");
         }
     }
View Code

 webconfig中配置:

技术分享
 <httpModules>
       <add name="clsHttpModule" type="WebDemo1.Common.clsHttpModule"/>
  </httpModules>
View Code

页面第一次加载效果:

技术分享

点击button按钮后:

技术分享

HttpModule

HttpModule通过在某些事件中注册,把自定义HttpModule插入ASP.NET请求处理管道。当这些事件发生的时候,ASP.NET调用对相应的HTTP模块,这样该模块就能处理请求了。

常用操作:

1、向每个页面动态添加一些备注或说明性的文字:
2、判断用户登录

如果定义了多个HttpModule,在web.config文件中引入自定义HttpModule的顺序就决定了多个自定义HttpModule在处理一个HTTP请求的接管顺序。

HttpHandler
HttpHandler是HTTP请求的处理中心,真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。

为了验证请求是否进入HttpHandler ,我们可以在WebConfig中 加入:

<add verb="*" path="*.aspx" type="WebDemo1.Common.clsHttpHandler,WebDemo1"/>

调试程序看看。

综上我们可以总计出一张图:

技术分享

 

ASP.NET页面事件

     在上面的部分,我们已经看到了一个ASP.NET页面完整的请求事件。 最重要的部分之一,是ASP.NET页面。我们详细讨论下ASP.NET的页面事件。任何ASP.NET页面中有2个部分 如图:

技术分享

注意 :大部分的开发者直接使用page_load方法的一切,这不是一个好的做法。例如 填充控件,设置视图状态,应用主题等,这些都是发生在页面上的负荷。因此,我们可以在适当的事件,添加适当的逻辑,这将真正使你的代码整洁 符合逻辑。

序号 事件  控件初始化 状态 是否
可用
表单数据是否
可用
什么逻辑可以写在这里?
1 Init No No No

OnInit 方法执行创建 Page 实例所需的初始化和设置步骤。在页生命周期的此阶段中,页中声明的服务器控件都已初始化为默认状态;但每个控件的视图状态尚未填充。在 Page_Init 阶段中,页中的控件不能访问该页的其他服务器控件,无论其他控件是子控件还是父控件。不一定会创建其他服务器控件,也不一定能够访问它们。

Load view state Not guaranteed Yes Not guaranteed 可以访问视图状态和任何同步逻辑
3 PostBackdata Not guaranteed Yes Yes 可以访问表单数据。
Load Yes Yes Yes 绑定控件 等等。。。
Validate Yes Yes Yes 如果页面有验证,或者你想为您的网页执行验证。
6 Event Yes Yes Yes 如果这是通过点击一个按钮或下拉的变化,那么相对应的事件将被执行。
Pre-render Yes Yes Yes 控件视图状态最后保存之前修改UI对象的结构或属性值。
8 Save view state Yes Yes Yes 一旦所有服务器控件的变化完成,这一事件控制数据保存在视图状态。
Render Yes Yes Yes 如果你想添加一些自定义的HTML输出。
10  Unload Yes Yes Yes

你可以在这里做任何清理。

 

 

技术分享

 

以上是关于ASP.NET应用程序与页面生命周期的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET 应用程序生命周期 - 不是页面生命周期 [重复]

[译] ASP.NET 生命周期 – ASP.NET 请求生命周期

WebForm页面生命周期及asp.net运行机制

ASP.NET页面生命周期包括哪几个阶段

ASP.NET MVC 生命周期 - 每个页面请求做一些工作

asp.net-页面生命周期