Gestión de una aplicación completa con .NET Servicio de Informática TEMA 4: FLUJO DE UNA APLICACIÓN 1. EVENTOS EN ASP.NET Los eventos en ASP.NET se clasifican en tres grupos: • (1) Eventos a nivel de aplicación. Son eventos globales de nuestra web, como pueden ser el inicio de la aplicación, finalización de una sesión, etc • (2) Eventos a nivel de página. Habitualmente lanzados por el usuario, como el submit de un formulario o pulsar sobre un enlace (http://msdn.microsoft.com/eses/library/ms178472.aspx). • (3) Eventos a nivel de servidor. Son los eventos propios de los controles de servidor de los Web Forms Eventos en el ciclo de vida de una aplicación web Una aplicación web inicia propiamente su existencia cuando un cliente se conecta a su página de inicio (es el inicio de una sesión). El servidor web Internet Information Server (IIS) levanta el proceso aspnet_wp.exe (en caso de ser necesario, podría estar ya activo con el servidor dando servicio) y carga el ensamblado DLL que contiene el código programado de la página solicitada y que se ejecuta en lado servidor. El servidor crea una instancia del Web Form solicitado, lo completa accediendo a los recursos e información necesarios, ejecuta la lógica de negocio y emite como respuesta ese Web Form en formato HTML al browser cliente. Tras esto, la instancia del Web Form y sus recursos son liberados de memoria. El ciclo se repite: el usuario rellena un formulario HTML, envía los datos al servidor, éste crea un Web form, le asigna los datos enviados y procesa los eventos, envía el Web form resultante como HTML y se libera junto con sus recursos. Vemos cómo los el ciclo de vida de un Web Form es muy corto. Tema 4 / Página 1 Gestión de una aplicación completa con .NET Servicio de Informática Sin embargo, la aplicación web sigue viviendo hasta que todas las sesiones a las que está dando servicio finalizan. Tras un tiempo sin atender nuevos eventos en una sesión, el servidor destruye la sesión, y cuando no queda ninguna activa, finaliza la aplicación web (el CLR libera de memoria los recursos de la aplicación tales como el DLL cargado) y se lanza un evento Application_End. Si queremos que la información persista entre las distintas instancias volátiles y sin estado de los Web form, podemos hacer uso de dos niveles de ámbito en el servidor: • Variables a nivel de aplicación. Es un espacio global existente en todo el ciclo de vida de la aplicación web, y accesible desde todas las sesiones a las que ésta da servicio en un determinado momento. • Variables a nivel de sesión. La aplicación web tiene reservados tantos espacios de memoria reservados como sesiones tenga activas y reducidas a su ámbito e inaccesibles fuera de ellas (independientes entre sí). Tema 4 / Página 2 Gestión de una aplicación completa con .NET Servicio de Informática (1) Eventos de las aplicaciones y de las sesiones La signatura de los métodos son de la forma protected void <nombre manejador>(object sender, EventArgs e) { } Ejemplo: protected void Application_Start(object sender, EventArgs e) { } <nombre_manejador> pueden ser: Manejador de evento Acción asociada Application_Start Primera visita a la página inicio de la aplicación web Application_BeginRequest Inicio petición al servidor (solicitar una página) Application_EndRequest Fin de petición al servidor (la página ya ha sido solicitada) Application_End Todas las sesiones de usuario expiran Application_AuthenticateRequest Petición de autenticación Application_Error La aplicación lanza un error Session_Start Un nuevo usuario solicita una página de la aplicación web Session_End Un usuario deja de hacer peticiones a la aplicación web y su tiempo de sesión expira. Los manejadores de eventos se encuentran definidos en el fichero del proyecto Global.asax: Ejemplo 1: Queremos contar el número de veces que el servidor recibe los eventos de un internauta. Para ello utilizamos variables de estado para almacenar objetos en memoria en sus distintos ámbitos ('Application' para aplicación y 'Session' para sesión): void Application_Start(object sender, EventArgs e) { // Código que se ejecuta al iniciarse la aplicación Application["aplicacionesActivas"] = 0; Application["sesionesActivas"] = 0; //Incrementamos Application["aplicacionesActivas"] = (int)Application["aplicacionesActivas"] + 1; } Tema 4 / Página 3 Gestión de una aplicación completa con .NET Servicio de Informática void Session_Start(object sender, EventArgs e) { // Código que se ejecuta cuando se inicia una nueva sesión Application["sesionesActivas"] = (int)Application["sesionesActivas"] + 1; Response.Write("Aplicaciones activas " + Application["aplicacionesActivas"] + "<br />"); Response.Write("Sesiones activas " + Application["sesionesActivas"]); } Ahora podemos probar: Ejemplo 2: Vamos a probar el resto de eventos del global.aspx: protected void Application_BeginRequest(Object sender, EventArgs e) { Response.Write("<p><b>[Aplication_BeginRequest]</b>:comienza la respuesta del navegador</p><br />"); } protected void Application_EndRequest(Object sender, EventArgs e) { Response.Write("<p><b>[Aplication_EndRequest]</b>:acaba la respuesta del navegador</p><br />"); } void Session_End(object sender, EventArgs e) { Application["sesionesActivas"] = (int)Application["sesionesActivas"] - 1; } Tema 4 / Página 4 Gestión de una aplicación completa con .NET Servicio de Informática Ahora bien: dos pestañas de un mismo navegador se interpretan como dos peticiones dentro de una misma sesión (son dos instancias de un mismo browser contenedor). Por eso en la siguiente captura sólo se muestran las trazas de la request y no se captura ningún evento de inicio de sesión porque ésta ya la inició: (2) Eventos de los Web Form Si una página la hemos programado con un Web Form, podemos utilizar los siguientes eventos: Manejador de evento Acción asociada Page_PreInit Se genera cuando la fase de inicio se ha completado y antes de que comience la fase de inicialización. Utilice este evento para lo siguiente: Page_Init • Examine la propiedad IsPostBack para determinar si es la primera vez que se procesa la página. En este momento también se han establecido las propiedades IsCallback e IsCrossPagePostBack. • Crear o volver a crear controles dinámicos. • Establecer una página maestra de forma dinámica. • Establecer la propiedad Theme de forma dinámica. • Leer o establecer los valores de las propiedades de perfil. El servidor crea una instancia del Web Form, carga sus controles y los inicializa con lo recibido del estado de la vista (datos del browser del cliente que vienen con la Tema 4 / Página 5 Gestión de una aplicación completa con .NET Servicio de Informática request). El evento Init de controles individuales se produce antes del evento Init de la página. Utilice este evento para leer o inicializar las propiedades del control. Page_Load Los controles del servidor se cargan en un nuevo objeto de tipo Page. Ahora el programador puede acceder a la información de la vista y manejar los controles de la página, contenido, etc. Eventos de control Utilice estos eventos para controlar eventos de control específicos, como un evento Click del control Button o un evento TextChanged del control TextBox. (Ver punto siguiente) Page_PreRender El objeto Page va a renderizarse en código interpretable por el browser en cuanto finalice este evento. El objeto Page genera el evento PreRender en e el objeto Page y, a continuación, vuelve a hacer lo mismo para cada control secundario. El evento PreRender de controles individuales se produce después del evento PreRender de la página. Page_Unload El objeto Page deja de ser referenciable, enciable, se destruye. destruy Page_Disposed La memoria ocupada por Page es liberada. Page_Error Evento iniciado cuando se ha producido una excepción no capturada. Page_AbortTransaction Una operación transaccional ha sido finalizada sin llegar a su fin. Page_CommitTransaction La transacción se ha completado con éxito. Page_DataBinding Un control de servidor se ha conectado a una fuente de datos. Tema 4 / Página 6 Gestión de una aplicación completa con .NET Servicio de Informática Ejemplo: public partial class _Default : System.Web.UI.Page { protected void Page_PreInit(object sender, EventArgs e) { Response.Write("<b>[Page_PreInit]</b>"); if (Page.IsPostBack) Response.Write(Request.Form["TextBox1"] + "<br />"); } protected void Page_Init(object sender, EventArgs e) { Response.Write("<b>[Page_Init]</b><br />"); TextBox1.Text = "Page_init"; } protected void Page_Load(object sender, EventArgs e) { Response.Write("<b>[Page_Load]</b><br />"); } protected void Page_PreRender(object sender, EventArgs e) { Response.Write("<b>[Page_PreRender]</b><br />"); } } (3) Eventos de los controles de servidor Grupos de eventos de los controles: • Eventos de envío. Son los eventos lanzados por controles que emiten un envío (post) al servidor de manera inmediata para procesar el Web Form. Por ejemplo al enviar un formulario pulsando sobre el botón de aceptación. Estos controles son: Button, Link Button e Image Button. • Eventos de caché. Estos eventos se producen en la vista y serán procesados en el servidor cuando se envíe la información mediante un evento de envío. Por ejemplo el seleccionar un elemento de una lista provoca un cambio de estado de la misma que luego, en servidor, podremos obtener. Controles con eventos de caché son TextBox, DropDownList, CheckBox. Tema 4 / Página 7 Gestión de una aplicación completa con .NET Servicio de Informática • Eventos de validación. Son los eventos que se procesan dentro de la página web. Por ejemplo que la entrada sea obligatoria. En el ciclo de vida de un Web Form se aplica el siguiente algoritmo de manejo de eventos: 1. Los controles con validación hacen las validaciones en el propio cliente antes de que la página sea enviada al servidor (se ha tenido que producir un evento de envío previamente). 2. La página se envía y se suceden los eventos Page_Init y Page_Load. Se procesan los eventos cacheados por orden temporal y finalmente se procesa el evento de envío. 3. Nuestra lógica de negocio realiza las acciones pertinentes con los controles. Insertamos este código en nuestro default.aspx de pruebas: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"><title>Página sin título</title></head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text="Nombre" AssociatedControlID="TextBoxNombre"></asp:Label> <asp:TextBox ID="TextBoxNombre" runat="server" ontextchanged="TextBoxNombre_TextChanged" onload="TextBoxNombre_Load" onprerender="TextBoxNombre_PreRender"></asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" Tema 4 / Página 8 Gestión de una aplicación completa con .NET Servicio de Informática ErrorMessage="Introduce el nombre" ControlToValidate="TextBoxNombre"> </asp:RequiredFieldValidator> <asp:Button ID="Button1" runat="server" Text="Enviar" onclick="Button1_Click" /> </div> </form> </body> </html> using System; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.Write("[Page_Load] " + TextBoxNombre.Text + "<br />"); } protected void Button1_Click(object sender, EventArgs e) { Response.Write("[Servidor] Click en el botón " + TextBoxNombre.Text + "<br />"); } protected void TextBoxNombre_TextChanged(object sender, EventArgs e) { Response.Write("[Servidor] Texto cambiado "+ TextBoxNombre.Text+"<br />"); } protected void TextBoxNombre_Load(object sender, EventArgs e) { Response.Write("[Servidor] Control cargado " + TextBoxNombre.Text + "<br />"); } protected void TextBoxNombre_PreRender(object sender, EventArgs e) { Response.Write("[Servidor] Control pre Renderizado " + TextBoxNombre.Text + "<br />"); } } Pulsamos del botón Enviar con el campo obligatorio vacío y el propio navegador gestiona los eventos de validación y se omite la request: Tema 4 / Página 9 Gestión de una aplicación completa con .NET Servicio de Informática Si introducimos valor en el campo podemos: mostrar el orden en el que el servidor maneja los eventos del Web Form: Tema 4 / Página 10 Gestión de una aplicación completa con .NET Servicio de Informática 2. TRAZA EN ASP.NET Definición: Se puede utilizar la traza para hacer un seguimiento del flujo de ejecución de una aplicación, mostrar datos en puntos críticos del ciclo de vida de un formulario Web Forms y detectar cómo interactúan los formularios Web Forms con otros componentes de la aplicación. Mediante la traza puede examinar los parámetros de solicitud HTTP que se envían a su aplicación, cuánta memoria se está almacenando en el estado de vista para un formulario Web Forms determinado y otra información útil para la generación de perfiles. Funcionamiento: En la directiva page se añade Trace = “true” <%Page Language="C#" AutoEventWireup="true" CodeFile="formulario_nuevo_usuario_principal.aspx.cs" Inherits="_Default" MasterPageFile="~/MasterPage.master" Trace="true" %> Se pueden crear declaraciones de seguimiento en lugares estratégicos del objeto trace de la páginas. Para eso usamos Trace.Write / Trace.Warn. La diferencia esté en que el primero pintará en negro y el segundo en rojo. Se puede observar en la traza de la página siguiente como se ha puesto en Page_Load un Trace.Warn. protected void Page_Load(object sender, EventArgs e) { Trace.Warn("Page_Load"); } También se destaca la aparición de nuevos eventos de flujo cuando se hace postback. Tema 4 / Página 11 Gestión de una aplicación completa con .NET Servicio de Informática 3. ENLACES EN INTERNET http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=eventosASPNET http://msdn.microsoft.com/es-es/library/ms178472.aspx Tema 4 / Página 12