ASP.NET本质论
上QQ阅读APP看书,第一时间看更新

2.3.8 特殊的HttpApplication事件处理

通过global.asax文件,可以简单地完成一些特殊的事件处理,只要按照特定的命名形式,就可以使定义的方法自动注册到对应的事件中。在ASP.NET中,有些事件甚至只能通过global.asax来完成处理。

1.Start事件

这个事件并不是HttpApplication处理管道中的事件,当网站启动后,第一次请求到达网站之后,ASP.NET网站将首先触发一次这个事件,而且在网站的整个生命周期中,也仅仅会触发一次。

触发这个事件的事件源对象是System.Web.HttpApplicationFactory对象,而不是通常的HttpApplication,所以,也不能通过HTTPApplication对象来获取相关的请求参数。在这个事件触发的时候,第一次请求的上下文对象HttpContext也已经创建,所以,可以通过HTTPContext.Current获取第一次的上下文请求对象,然后,通过这个上下文对象来获取相关的信息。

由于这个事件在网站第一次请求的时候触发,所以非常适合针对网站全局的数据进行初始化工作,在ASP.NET MVC中,RouteTable就是在这个事件中创建的。

2.End事件

当网站应用程序被关闭的时候,将触发这个事件。

3.Error事件

当网站应用程序出现错误,或者处理过程中出现未捕获的异常时,HttpApplication将抛出这个事件。

这个事件的事件源是HttpApplication,当前的异常信息可以通过HTTPApplication的Server属性获取HTTPServerUtility的对象实例来完成。HttpServerUtility对象的GetLastError()方法将返回最后一次的异常,这个方法的定义如下:

public Exception GetLastError()

这个异常是一个经过包装的异常,它的InnerException属性指向网站最后一次抛出的未处理异常。

常见的处理如下:

void Application_Error(object sender, EventArgs e)
{
    HttpServerUtility server = (sender as HttpApplication).Server;
    Exception exception = server.GetLastError().InnerException;
    // 针对异常的处理
    // 清理这个异常
    server.ClearError();
}

4.Session的Start事件

当ASP.NET每次创建了一个新的Session后,换句话说,创建了一个新的Session ID之后,就会触发Session的Start事件。需要注意到,在ASP.NET中,支持会话的HttpModule在配置文件中注册的name就是Session。

5.Session的End事件

当一个Session过期之后,或者通过调用Abandon方法被丢弃之后,将会触发Session的End事件。这个事件的事件源实际上是SessionStateModule,而不是HttpApplication。需要注意的是,关闭浏览器并不会导致Session的End事件。而且,如果Session的管理模式是StateServer或者SQLServer的话,将不会触发这个事件。

6.HttpModule的事件注册

从Session的处理可以看出,对于注册到网站中的HttpModule,如果这些Module也会抛出事件,而我们希望能够处理这些HttpModule事件的时候,可以在global.asax中通过定义命名形式如HttpModule注册名称_事件名称的方法来处理HTTPModule的事件。当然,方法必须首先要符合事件的委托定义。

例如,在ASP.NET 2.0之后,提供了匿名用户的标识支持,这是通过一个注册名为AnonymousIdentification的HttpModule实现的,它同时提供了一个名为Creating的事件。定义事件的委托如下:

public delegate void AnonymousIdentificationEventHandler(
   Object sender,
   AnonymousIdentificationEventArgs e
)

那么,在global.asax中,可以定义如下命名形式的方法来处理这个事件。

public void AnonymousIdentification_Creating(
   object sender,
         AnonymousIdentificationEventArgs args
  )
{
}

类似的情况还有个性化数据Profile的事件处理。个性化数据是通过注册名为Profile的HttpModule进行处理的,它的实际类型为ProfileModule,这个类提供了一个名为MigrateAnonymous的合并匿名用户数据的事件,这个事件的委托定义如下:

public delegate void ProfileMigrateEventHandler(
   Object sender,
   ProfileMigrateEventArgs e
)

所以,可以在global.asax中定义如下形式的方法进行处理。

public void Profile_OnMigrateAnonymous(
   object sender,
   ProfileMigrateEventArgs args)
{
   ProfileCommon anonymousProfile
    = Profile.GetProfile(args.AnonymousID);
   ProfileManager.DeleteProfile(args.AnonymousID);
   AnonymousIdentificationModule.ClearAnonymousIdentifier();
   //Delete the user row that was created for the anonymous user.
   Membership.DeleteUser(args.AnonymousID, true);
}