Gerardo Contijoch

Experiencias del día a día trabajando con .NET – ASP.NET, C#, ASP.NET MVC y demas…

Investigando los eventos de la clase HttpApplication en ASP.NET

Posted by Gerardo Contijoch en junio 27, 2009

Hace unos días me encontré con este interesantísimo post de Rick Strahl en donde responde a una pregunta que alguien le hizo. La pregunta en cuestión es ¿Cómo es que los handlers de los eventos Application_ en ASP.NET son enlazados para que sean invocados automáticamente?

Es una pregunta interesante ya que normalmente uno enlaza a mano los eventos que desea capturar, pero en el caso de los eventos de la clase HttpApplication, la situación es diferente porque no podemos enlazarlos nosotros mismos (en realidad si podemos, pero no tiene ningún efecto). Veamos como es el asunto.

Cuando agregamos un archivo Global.asax a nuestro proyecto vemos que la clase Global ya posee algunos handlers creados:

   1: public class Global : System.Web.HttpApplication {
   2:
   3:     protected void Application_Start(object sender, EventArgs e) { }
   4:
   5:     protected void Session_Start(object sender, EventArgs e) { }
   6:
   7:     protected void Application_BeginRequest(object sender, EventArgs e) { }
   8:
   9:     protected void Application_AuthenticateRequest(object sender, EventArgs e) { }
  10:
  11:     protected void Application_Error(object sender, EventArgs e) { }
  12:
  13:     protected void Session_End(object sender, EventArgs e) { }
  14:
  15:     protected void Application_End(object sender, EventArgs e) { }
  16: }

Lógicamente, al handler Application_Start nunca vamos a poder enlazarlo nosotros mismos ya que el mismo es ejecutado cuando la aplicación se inicia, pero el resto parecería que si podría ser enlazado debido a que ocurre luego de la inicialización de la aplicación. Bueno, no es tan así.

Para empezar, Application_Start, Application_End y Session_End parecen handlers pero en realidad no existe ningún evento asociado a los mismos, por lo que no es posible enlazarlos de otra manera. La clase HttpApplicationFactory es la encargada de simular estos eventos con los métodos FireApplicationOnStart(), FireApplicationOnEnd() y FireSessionOnEnd().

Segundo, el resto de los handlers no son mas que accesos directos a los eventos de distintos módulos (clases que implementan IHttpModule) que pueden ser cargados. Estos módulos son configurados en el archivo web.config en la seccion <httpModules>. Por ejemplo, uno de los que se carga por defecto es el llamado Session (de tipo System.Web.SessionState.SessionStateModule). El mismo es el encargado de mantener una sesión entre distintos requests y su carga esta definida en el archivo web.config que se encuentra en %WIN_DIR%\Microsoft.NET\Framework\[VERSION_FRAMEWORK]\CONFIG\ (este web.config se carga para todas las aplicaciones que se corran en nuestro equipo). Si en el web.config de nuestra aplicación agregamos la siguiente línea a la sección <httpModules>:

   1: <remove name="Session"/>

veremos que el handler Session_Start no se ejecuta más, ya que no hay ningún módulo llamado Session que provoque un evento Start (y como consecuencia, nuestra aplicación ya no tiene soporte para sesiones). Como no tenemos acceso a esos módulos sino hasta que la aplicación ya haya sido inicializada, no hay manera de enlazar esos eventos con los handlers y por eso necesitamos estos accesos directos que nos provee la clase HttpApplication.

Como se puede ver en el artículo original de Rick Strahl, el enlace ocurre en un método llamado HookupEventHandlersForApplicationAndModules() (con ese nombre, ¿a alguien le queda alguna duda de ello?). Resumiendo la funcionalidad del método, básicamente lo que sucede es que, dado un array de objetos MethodInfo (son cada uno de los handlers que creamos), se itera sobre ellos y se determina si el evento es de la aplicación o pertenece a algún módulo. Esto se logra buscando el ‘_’ en el nombre del mismo y tomando la primer parte. Luego se guarda una referencia a la instancia de HttpApplication o al módulo y se busca via reflection el evento en base al nombre del método (el evento ‘Start’ se asocia al método terminado en ‘Start’, por ejemplo). Un detalle curioso es que esta lógica reconoce a ‘Application_BeginRequest’ y a ‘Application_OnBeginRequest’ como lo mismo, teniendo precedencia el primero si es que se encuentran ambos presentes. Luego se valida que el handler tenga los parámetros correctos y si no es así, se genera un proxy para el mismo (lo que significa que nuestros handlers pueden no aceptar ningún parámetro y van a a ser igual de válidos). Finalmente después de obtener una referencia al evento correcto, se invoca al método Add del mismo para asociar nuestra instancia de MethodInfo (o el proxy que mencioné hace un momento) al evento y de este modo, cuando ocurra, se ejecuta nuestro handler.

¿Muy complicado? Si, seguro, la clase HttpApplication es una de las más complejas de .NET Framework, pero eso es lo que la hace interesante, ¿no?

¡Nos vemos en el próximo post!

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: