Eventos del ciclo de vida cliente en ASP.NET AJAX

21. February 2010 19:53 by Oscar.SS in Desarrollo .NET, Desarrollo Web  //  Tags: , ,   //   Comments (9)
Como ya hemos comentado alguna vez, ASP.NET con AJAX provoca en el servidor los mismo eventos que durante un PostBack en el ciclo de vida de una página. Pero además, cuando tenemos habilitado AJAX en nuestra página, provoca eventos en el ciclo de vida cliente. El conocer estos eventos y su ciclo es muy importante para tener el mayor control y manejo posible de las solicitudes asíncronas.
 
Estos eventos en el cliente son provocados por las clases de la librería de AJAX .NET. Esta librería y las instancias de sus clases están a nuestra disposición automáticamente al incluir un control ScriptManager al inicio de nuestras páginas.
 
Son dos las clases principales que provocan estos eventos durante el ciclo de vida de la página en el cliente. Tenemos la clase Sys.Application que para entendernos es similar a la clase Page del objeto de servidor. Y tenemos la clase Sys.WebForms.PageRequestManager.
 
Veamos por partes como ocurre todo tanto durante un petición síncrona (PostBack), como una petición asíncrona (AJAX).
 
 
Ciclo de eventos cliente durante un PostBack
 
Cuando arrancamos por primera vez nuestra aplicación, o cuando hacemos un viaje al servidor de nuevo, el ciclo de eventos que se provocan en el cliente son los siguientes.
  • Window.load(). Este evento del DOM como ya sabemos se dispara cuando se carga nuestra página.
  • PageRequestManager.pageLoaded(). Este evento se dispara tanto durante una llamada asíncrona como una síncrona cuando se ha actualizado todo el contenido de la página. Es el evento ideal para determinar en el código cliente si la devolución de datos fué realizada por AJAX o por un PostBack.
  • Application.init(). Se dispara cuando se terminan de cargar todos los script de cliente pero antes de que se cree ningún objeto de estos. Es decir, que si intentamos acceder durante este evento a cualquiera de los objetos declarados en nuestros script recibiremos un error. Otra cosa muy importante a tener en cuenta en este evento es que se dispara una única vez por cada devolución de datos síncrona, nunca durante una devolución asíncrona.
  • Application.load(). Este evento se dispara cuando se han cargado todos los objetos de los script de la página.
  • Application.unload(). Entra en acción antes de eliminar todos los objetos script de la página.
  • Window.unload(). Este evento del DOM como se dispara cuando se cierra nuestra ventana del explorador.

 
Ciclo de eventos cliente durante AJAX en .NET
 
Ahora viene lo que realmente debemos tener en cuenta. No olvidemos que estamos trabajando bajo el esquema de un control ScriptManager y un control UpdatePanel en nuestra página. Esto significa que cuando el servidor nos devuelve los datos, se realiza una actualización parcial de la página, en concreto, solo obtenemos el HTML necesario para repintar el contenido de los elementos del interior del UpdatePanel.

  • PageRequestManager.initializeRequest(). Este es el primero de los eventos que se disparan cuando provocamos una llamada AJAX. En realidad, durante este evento aún no ha comenzado la solicitud, por lo tanto, es el evento ideal para cancelar la llamada desde nuestro código cliente.
  • PageRequestManager.beginRequest(). Se provoca antes de que se envíen los datos al servidor. Es el último evento que se produce en el cliente. Es el momento ideal para llamar a un script personal que inicie una animación que notifique al usuario que se está procesando la devolución de datos. El control UpdateProgress hace uso de este evento para mostrar su contenido.
  • PageRequestManager.pageLoading(). Se dispara después de recibir la respuesta del servidor durante una llamada AJAX, pero antes de actualizar cualquier contenido en la página. Es una oportunidad perfecta para realizar cualquier acción personalizada, antes de ser pintados, sobre los datos recibidos desde el servidor, como filtrarlos o formatearlos. También es el evento usado para enviar datos a los controles que no están incluidos en el updatepanel.
  • PageRequestManager.pageLoaded(). Este evento se dispara tanto durante una llamada asíncrona como una síncrona cuando se ha actualizado todo el contenido de la página. Es el evento ideal para determinar en el código cliente si la devolución de datos fué realizada por AJAX o por un PostBack.
  • Application.load(). Este evento se dispara cuando se han cargado todos los objetos de los script de la página.
  • PageRequestManager.endRequest(). Se dispara después del repintado parcial de la página y se devuelve el control al explorador. También se dispara este evento cuando se ha producido un error durante la devolución de datos asíncrona. Si se produce un error, la página no se actualiza por lo tanto los datos devueltos por el servidor no son mostrados. Se puede utilizar este evento para proporcionar una notificación de error personalizada a los usuarios o para registrar los errores. También se utilizar para ejecutar script personalizados al terminar la devolución de datos asíncrona.
 
 
Pues muy bien, mucho rollo pero...¿como se declaran estos eventos en el cliente?. Pongamos todo esto en práctica.
<script type="text/javascript" language="javascript">

        
//Eventos del objeto Application

        
Sys.Application.add_init(applicationInitHandler);

        function 
applicationInitHandler() {
        
//Código para este evento
        
}


        
//Eventos del objeto PageRequestManager

        
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(prmInitializeRequest);

        function 
prmInitializeRequest() {
        
//Código para este evento
        
}
 </script>
La clase Sys.Application se instacia directamente, no así la clase Sys.WebForms.PageRequestManager que para intstanciarla debemos utilizar el método getInstance().
 
Los eventos de ambas clases se declaran al estilo de los delegados de C#, y siempre siguen la misma sintaxis: add_nombreEvento (nombreFuncion)
 
Podéis descargaros un pequeño ejemplo para jugar con todo esto: EventosClienteAJAX.rar (3,52 kb)
 
 

Ejemplo de CAPTCHA en ASP.NET

14. February 2010 01:55 by Oscar.SS in Desarrollo Web  //  Tags:   //   Comments (1)

Este sencillo ejemplo mostrará como implementar un controlador de peticiones HTTP personalizado para servir una imagen a modo de CAPTCHA. Naturalmente esto es solo un punto de partida muy simple y se podría complicar más para, por ejemplo, construir un control de servidor tipo CAPTCHA.

Para implementar nuestro controlador de peticiones HTTP personalizado debemos utilizar la interfaz IHttpHandler. Esta interfaz define el contrato que deben tener todos los tipos que se utilicen para manejar las peticiones HTTP. De esta forma podemos decidir qué y cómo se devuelve la solicitud desde el servidor.

A continuación dejo el código de la clase que implementa esta funcionalidad.

public class CaptchaHandler : IHttpHandler
{
    
public static string RndTexto { get; set; }
    
private char[] Abc;

    public 
CaptchaHandler()
    {
        Abc 
= new char[]{
            
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','Ñ','O','P','Q','R','S',
            
'T','U','V','W','X','Y','Z'};
        
InitRndTexto();
    
}
    //Creamos un texto aleatorio de 6 letras.
    
private void InitRndTexto()
    {
        Random Rnd 
= new Random();
        
System.Text.StringBuilder Sb = new System.Text.StringBuilder();

        for 
(int 0i < 6i++)
        {
            Sb.Append(Abc[Rnd.Next(
027)]);
        
}

        RndTexto 
Sb.ToString();
    
}

    
#region Miembros de IHttpHandler

    
public bool IsReusable
    {
        
get return false; }
    }

    
public void ProcessRequest(HttpContext context)
    {
        Bitmap Imagen 
= new Bitmap(18080, PixelFormat.Format16bppRgb555);
        
Graphics Grafico Graphics.FromImage(Imagen);

        
//Escribimos el texto.
        
Font Fuente = new Font(new FontFamily("Chiller"), 35, FontStyle.Italic);
        
Grafico.DrawString(RndTexto, Fuente, Brushes.Red, 1015);

        
//Dibujamos dos lineas.
        
for (int 0i < 2i++)
        {
            Point A 
= new Point(5, (35 + i * 10));
            
Point B = new Point(175, (35 + i * 10));
            
Grafico.DrawLine(new Pen(Brushes.Black, 3), A, B);
        
}

        context.Response.ContentType 
"Image/jpeg";
        
Imagen.Save(context.Response.OutputStream, ImageFormat.Jpeg);
    
}

    
#endregion
}

 

No hay mucho que explicar. En primer lugar generamos un texto aleatorio y lo guardamos en el campo RndTexto. Este campo publico podrá ser utilizado por otra clase cliente para comprobar, por ejemplo, que el texto introducido por el usuario coincide con el de la imagen. Después escribimos el texto aleatorio sobre una superficie de dibujo. También dibujamos dos lineas horizontales para dificultar un poco su lectura. 

Debemos registrar en el web.config este controlador HTTP para que ASP.NET sepa que debe hacer cuando entra una petición en el servidor.

      <system.web>
        
<httpHandlers>
            
<add verb="*" type="CaptchaHandler" path="*.captcha"/>
        </
httpHandlers>
      
</system.web> 

Con esta configuración estamos indicando (por orden) que para cualquier tipo de petición GET o POST, debe ser manejada por el tipo CaptchaHandler. Por último, indicamos que cuando se solicite un archivo con extensión captcha nuestro controlador debe actuar sirviendo la respuesta implementada en el código.

Desde este momento, siempre que el código cliente solicite una imagen con la extensión indicada, se le servirá nuestro CAPTCHA personalizado. Es decir, al encontrarse con algo como lo siguiente:

        <img alt="" src="sitioWeb.captcha" />

Obtendremos una salida en el explorador cliente como esta.

 

 

Quizás el diseño no sea muy acertado, pero dejo para vosotros el mejorarlo ;-)

Instalar la libería de AJAX Control Toolkit

7. February 2010 18:21 by Oscar.SS in Desarrollo .NET, Desarrollo Web, Herramientas  //  Tags: , ,   //   Comments (2)

La biblioteca de controles AJAX Control Toolkit es una poderosa característica que debemos tener siempre presente. Por ello vamos a ver como se instala en 7 sencillos pasos, para que quede integrada en nuestra herramienta de desarrollo Visual Studio 2008.

1. En primer lugar debemos dirigirnos al sitio oficial de descarga, que no es otro que CodePlex. En el siguiente enlace buscaremos la zona de descarga.

http://ajaxcontroltoolkit.codeplex.com/

 

2. Elegimos la versión que queremos descargar y descomprimimos el zip. En el momento de escribir este artículo esta disponible la versión que se muestra en la imagen.

 

3. Nos dirigimos a nuestro Visual Studio y abrimos un editor de páginas aspx. En el cuadro de herramientas, en la última ficha, "General", con el botón secundario seleccionamos la opción "Agregar Ficha". Le damos un nombre a la nueva ficha, por ejemplo, AJAX Control Toolkit.

 

4. Sobre la superficie de la nueva ficha repetimos la operación y esta vez seleccionamos "Elegir Elementos".

 

5. En la ventana que se abre, elementos del cuadro de herramientas, presionamos el botón "Examinar".

 

6. Buscamos la carpeta que acabamos de descargar y dentro de ella seleccionamos la siguiente dll. 

........./SampleWebSite/Bin/AjaxControlToolkit.dll

 

7. Presionamos el botón "Aceptar" y esperamos a que terminen de cargarse todos los binarios. Y ya tenemos todos los controles de AJAX en el cuadro de herramientas listos para ser utilizados.

¡A disfrutarlo! 

IHttpModule: Antes y después de la solicitud

30. January 2010 14:23 by Oscar.SS in Desarrollo .NET, Desarrollo Web  //  Tags: ,   //   Comments (0)

La interfaz IHttpModule nos proporciona una manera simple de manejar las peticiones HTTP antes de que estas comiencen a administrarse en IIS y una vez que han sido totalmente ejecutadas y se van a devolver al cliente.

¿Porque razón querríamos actuar en la solicitud antes (y después) de que comience a administrarse? 

  • Por temas de seguridad y rendimiento. Si un usuario no tiene permisos en nuestra aplicación es mejor denegarle el acceso antes de que su solicitud comience a consumir recursos en el servidor.  Comprobamos que no tiene premisos antes del comienzo de ejecución de ninguno de los eventos del ciclo de vida de la página solicitada (o control de usuario, o servicio Web).
  • Para crear módulos estadísticos sobre las solicitudes de forma global en lugar de hacerlo para las páginas de forma individual.
  • Incluir en la respuesta a la solicitud, encabezados y pies de páginas personalizados para todas las solicitudes.
  • En general, siempre que deseemos actuar antes de que comience a ejecutarse la solicitud en el servidor y justo antes de que se envíe la respuesta al cliente.
 
 
 
La forma de implementar un módulo es muy sencilla. Solo tenemos que crear un archivo de clase, por ejemplo Modulo.cs, y implementar la interfaz IHttpModule. Los miembros de esta interfaz son solo dos. 
  • Init(). Inicializa el módulo y lo prepara para procesar la solicitud HTTP.
  • Disponse(). Elimina los recursos utilizados por el módulo.
Es evidente que la lógica de nuestro módulo deberá implementarse en el método Init(). A continuación podemos ver un sencillo ejemplo que comprueba si el usuario tiene permisos, en caso negativo es transferido a una página en la que se muestra un mensaje.
 
public class ClaseModulo : IHttpModule
{
    
public ClaseModulo(){}

    
public void Dispose() { }

    
public string NombreModulo 
    {
        
get return "MiModulo"}
    }

    
public void Init(HttpApplication aplicacion)
    {
        
/*
         * Definimos los eventos del ciclo de vida de la aplicación sobre los que vamos actuar.
         * En este caso actuamos antes del comienzo de la solicitud y cuando esta termina.
         */
        
aplicacion.BeginRequest += new EventHandler(aplicacion_BeginRequest);
        
aplicacion.EndRequest += new EventHandler(aplicacion_EndRequest);
    
}

    
private void aplicacion_BeginRequest(object sender, EventArgs e)
    {
        
//Obtenemos el contexto de aplicación de la solicitud.
        
HttpApplication Aplicacion (HttpApplication)sender;
        
HttpContext Contexto Aplicacion.Context;

        
//Obtenemos la extensión del archivo solicitado.
        
string Ruta Contexto.Request.FilePath;
        string 
Extension VirtualPathUtility.GetExtension(Ruta);

       
//Si se ha solicitado una página aspx.
        
if (Extension.Equals(".aspx"))
        {
            
//Si el usuario no tiene permisos le enviamos a la página de error.
            
if (!UserTienePermisos())
            {
                Contexto.Server.Transfer(
"Default2.aspx");
            
}
        }
    }

    
private void aplicacion_EndRequest(object sender, EventArgs e)
    {
        
//Obtenemos el contexto de aplicación de la solicitud
        
HttpApplication Aplicacion (HttpApplication)sender;
        
HttpContext Contexto Aplicacion.Context;

        
//Obtenemos el nombre del archivo solicitado.
        
string Ruta Contexto.Request.FilePath;
        string 
Extension VirtualPathUtility.GetExtension(Ruta);

        if 
(Extension.Equals(".aspx"))
        {
            
//Si el usuario no tiene permisos mostramos un mensaje al final de la solicitud.
            
if (!UserTienePermisos())
            {
                Contexto.Response.Write(
"Usted no tiene permisos");
            
}
        }
    }
}
 
Una vez codificada la lógica de nuestro módulo debemos registrarlo en el web.config para ASP.NET tenga en cuenta como tiene que manejar la solicitud.
        <system.web>
            
<httpModules>
                
<add name="MiModulo" type="ClaseModulo"/>
            </
httpModules>
        
</system.web>

Recopilación y actualización a la versión .NET 4.0

14. January 2010 22:00 by Oscar.SS in Desarrollo .NET, Desarrollo Web, Información  //  Tags: , ,   //   Comments (0)

Con motivo del cercano lanzamiento de .NET Framework 4.0, me ha dado por actualizar la información que tenía en este blog de la evolución de .NET desde la versión 1.0. Por ello me he kurrado un gráfico que creo servirá para aclarar el tema del versionado de Microsoft que ciertamente es un jaleo :-(

Y ya de paso he aprovechado para modificar un poco las páginas que podéis encontrar en el menú de la izquierda, donde pone Páginas Extra, referentes a las novedades de C# 2.0C# 3.0C# 4.0. Bueno, en realidad la última versión del lenguaje no la he incluido, aún estoy recopilando la información...sorry!!.

Aquí os dejo el gráfico (click para ampliar).

 

 

Mi idea principal con este gráfico, es dejar más clara la evolución de las tecnologías disponibles en cada versión del framework en cuando a desarrollo con ASP.NET.

Por este motivo podéis encontrar en la fila correspondiente a ASP.NET (color rojo) algunas tecnologías que se han incluido en el framework pero que en realidad no pertenecen al núcleo de ASP.NET. Pero si tienen mucho que ver con el desarrollo web en ASP.NET.

Como referencia, comentar que parte de la información la he extraido del libro de José Manuel Alarcón titulado muy acertadamente "Tecnologías ASP.NET 4.0 (Saltando desde la versión 2.0)".

Por otra parte, animo a todos a comentar cualquier cosilla que se me pase por alto o que sea de interés común incluirlo en el gráfico. 

Recent Comments

Comment RSS

Month List