Redireccionamiento en Session_End Fecha: 01/Feb/2005 (Enero 30, 2005)
|
Como todo desarrollador, a la hora de estar diseñando aplicaciones que involucren operaciones de Login, Logout y Timeouts para varios usuarios, eventualmente te encontrarás con la situacion en que quieres especificar una página a la que los usuarios sean redireccionados despues de un Timeout.
Cierto, el Framework nos deja trabajar de manera muy sencilla y fácil, provee muchos eventos para manejar casi cualquier tipo de situación. Sin embargo, siempre hay pequeños detalles.
Para especificar cuanto tiempo dura la sesion de un usuario antes de hacer timeout, simplemente utilizamos el comando:
Session.Timeout = 120;
Eso nos da un periodo de 120 minutos antes de que la sesión del usuario expire. Esta propiedad de Timeout tiene un valor maximo de 525,600 minutos (que vienen de 365dias x 24horas x 60minutos). Y para manejar eventos de la sesion especifica del usuario, siempre tenemos los eventos Session_Start y Session_End (ambos eventos se manejan en el archivo Global.asax), sin embargo, en este último evento, la lógica se rompe un poco.
Es lógico para nosotros el especificar código de limpieza de variables, conexiones, etc. en el evento Session_End. Si la sesión expiró y queremos redireccionarlo, NO podemos utilizar ningun tipo de comando de redirección en ese evento. Y no funciona debido a que los comandos de Response.Redirect() y Server.Transfer(), responden solamente cuando se hizo un Request manualmente, mientras que el evento Session_End se dispara automaticamente cuando una sesión expira o es abandonada programáticamente.
Y bueno, lo que queremos es simplemente realizar código de rutina en nuestro Session_End y al final, redireccionar al usuario a una página no? Lo que hacemos es, manejar como normalmente lo hariamos el código de terminación de sesión en el Session_End y solamente vamos a variar el lugar donde colocaremos el código de redirección a la pagina de timeout.
Si nuestra aplicación solo consta de pocas páginas, simplemente agregamos este código al evento Page_Load de cada una:
private void Page_Load(object sender, EventArgs e) {
Response.AddHeader("Refresh",Convert.ToString((Session.Timeout * 60) + 5));
if(Session["SesionActiva"]==null)
Response.Redirect("Login.aspx");
}Este código, nos permite agregar un Header de Refresh, el cual toma el valor programático de la propiedad Session.Timeout, sin embargo, debido a que el Header que agrega no pertenece al .NET Framework, es necesario multiplicarlo por 60 debido a que el valor que obtiene el Framework es en minutos, y para agregar el Header, el valor debe venir en segundos. Se le agregaron 5 segundos al Header para que la aplicación tenga tiempo de realizar el código que contenga el Session_End en el Global.asax y al terminar, refresque la página y verifique si la variable de session es nula, redireccione a la pagina que indica que la sesión expiró.
Esta solución es sencilla solo si nuestra aplicación no es grande. Por buena práctica, y más modularidad, lo ideal (y necesario, cuando nuestra aplicación es de mayor nivel o complejidad) es crear una clase base que herede de System.Web.UI.Page, le agregamos el metodo Page_Load del bloque de arriba, pero lo hacemos del tipo virtual.
Luego, hacemos que todas las páginas que queremos que tengan el redireccionamiento al pasar el Timeout, hereden de nuestra página base. Es necesario que en las paginas de la aplicacion, hagamos que el método Page_Load sea del tipo override y en el Page_Load de nuestra pagina normal, mandamos llamar el método Page_Load de nuestra pagina base a través de la instrucción:
base.Page_Load(sender, e);
Esto hace que se mande llamar el método global de Page_Load de la pagina BASE y luego todavia podemos tener código de Load específico de nuestra página actual, como puede ser el llenado de datos de una fuente de datos o cosas por el estilo.
Nuestros pasos serian:
1. Crear una clase Base que herede de System.Web.UI.Page, que tenga un metodo Page_Load del tipo virtual. El método contiene la lógica de agregar el Refresh header.
2. Hacer que todas nuestras paginas del sistema hereden de nuestra clase base.
3. En las paginas del sistema, hacer que el método Page_Load sea del tipo override y dentro del método, mandar llamar a base.Page_Load(sender, e).Código ejemplo para la clase base:
namespace RefreshArticle {
public class BasePage : System.Web.UI.Page {
protected virtual void Page_Load(object sender, EventArgs e) {
Response.AddHeader("Refresh",Convert.ToString((Session.Timeout * 60) + 5));
if(Session["SesionActiva"]==null)
Response.Redirect("Login.aspx");
}
}
}Y este sería el código ejemplo para una página normal del sistema, la cual hereda de nuestra página base que contiene el código de manejo de redirección.
public class WebForm1 : RefreshArticle.BasePage {
protected override void Page_Load(object sender, System.EventArgs e) {
base.Page_Load(sender, e);
Response.Write(Session.Timeout.ToString());
}
}En la pagina normal, el comando importante fue mandar la llamada al evento Page_Load de la pagina base, que hizo que se agregara el Refresh Header a nuestra página del sistema.
Espero que el artículo les haya servido.
Fichero con el código de ejemplo: GRP_RefreshArticle.zip - 23 KB