JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

AJAX con ASP.NET 2.0 (The "a pelo" series): Script Callbacks (II): La interfaz ICallbackEventHandler

Bueno, en el anterior post, ya hemos visto que para poder hacer uso de la característica de Callback nativa de ASP.NET 2.0 sólo hay que implementar la interfaz ICallbackEventHandler.

Ésta sólo tiene dos miembros:

  • Método RaiseCallbackEvent: Es llamado automáticamente cuando se produce un Callback al servidor mediante Script. Se le pasa como parámetro una cadena que se genera en el lado de cliente (en el navegador) antes del envío. Enseguida veremos la manera de hacerlo. Dentro de este método hacemos el procesamiento que necesitemos, por ejemplo, recibimos un identificador y vamos a una base de datos para obtener los datos de detalle de una entidad asociada. Cualquier cosa. Su definición es la siguiente:

void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)

  • Método GetCallbackResult: este es el método que se llama automáticamente para devolver los resultados al cliente. Dichos resultados se devuelven en forma de cadena (es el tipo devuelto por el método) y se pasan a una función JavaScript en el cliente. Es decir, en esta cadena podemos meter cualquier cosa en el formato que deseemos: valores separados por comas, XML, JSON, etc... Su definición es esta:

string ICallbackEventHandler.GetCallbackResult()

En la mayor parte de los artículos que hay en Internet sobre este tema viene documentado el funcionamiento de esta característica en las primeras betas de ASP.NET y eso ahora no funciona. Antes sólo había que implementar una función, que ya devolvía el resultado. Ahora son dos, por lo que os vemos obligados a usar una variable de clase, común a ambas, para devolver el resultado al cliente. Como ventaja tenemos que separamos el procesamiento de la llamda de su resultado de modo que, aunque se produzca un error en el evento, se sigue llamando igualmente a GetCallbackResult para devolver el resultado, y podemos jugar con eso.

Generar la llamada desde el cliente

Bien, ahora que ya sabemos cómo proceder en el servidor hay que proceder a provocar la llamada desde el cliente. Para ello hay que usar obviamente JavaScript, sólo que en esta ocasión no tendremos que "currárnoslo" nosotros, sino que ASP.NET proporciona todo lo necesario de manera automática. Para provocar la llamada al servidor hay que usar una función JavaScript llamada WebForm_DoCallback que toma unos determinados parámetros. Ésta está definida en uno de los manejadores AXD que ASP.NET incluye de manerta automática por nosotros y que genera JavaScript.

Eso sí, no debemos hacer uso de ella directamente. El hecho de que sepamos como se llama e incluso podamos averiguar para qué se usan sus parámetros no es motivo para que la usemos directamente. En versiones posteriores o revisiones de ASP.NET podría cambiar de nombre o de parámetros. Por eso, para evitarnos este problema, dentro de la clase ClientScript hay un método llamado GetCallbackEventReference que sirve precisamente para generar una llamada javaScript con el nombre y parámetros adecuados a esta función, obteniendo algo análogo a este código:

WebForm_DoCallback('__Page',document.getElementById('ddlCategorias').value,ActualizaVista,null,MuestraError,false)

Una nota importante respecto a esta función: en la mayor parte de los artículos que hay en Internet pone que GetCallbackEventReference es un método de la clase Page, cuando no es así. Desde la beta 1 de ASP.NET 2.0 esto cambió y pasó a formar parte (con muy buen criterio) de ClienteScript que sí es una propiedad de Page.

GetCallbackEventReference tiene tres versiones sobrecargadas que se pueden llamar. A la más común se le pasan los siguientes parámetros:

  • Control: una referencia al control ASP.NET que implementa la interfaz ICallbackEvetnHandler, y que obviamente puede ser la propia página actual (que hereda de Control).
  • Argumento JavaScript: la expresión JavaScript que se evaluará antes de enviar al servidor la petición y cuyo resultado es precisamente lo que recibiremos en el método RaiseCallBackEvent visto antes. Puede ser una simple cadena o número, o bien una expresión JavaScript completa que devuelva algún resultado.
  • Nombre de función JavaScript de retorno: el nombre de una función JavaScript que se llamará en el cliente cuando se devuelva la llamada del servidor. A ésta se le pasará el resultado devuelto por GetCallbackResult (una cadena), así como una variable de cadena para marcar el contexto de la llamada (información auxiliar opcional para saber desde donde se llama, como se explica en el siguiente parámetro).
  • Contexto: se trata de un identificador de contexto (puede ser una cadena cualquiera o un número, etc...) que servirá para identificar el contexto de la llamada. De este modo podemos reutilizar la misma función de cliente o de servidor (se recibe en ambas) pero tratarla de forma diferente según el contexto. Lo más habitual es pasarle un nulo.

JAX: ¡esto es SÍNCRONO por defecto!

Un momento la 'A' de 'AJAX' no es por 'Asíncrono'. Sí. Sin embargo, por defecto, con los parámetros pasados en el método anterior, WebForm_DoCallback, hace una llamada síncrona al servidor. No pasa nada, normalmente no notaremos diferencia, pero claro, en caso de tener conexión lenta (o fallar) podríamos notar una cierta paralización de la interfaz del navegador. Por ello es recomendable utilizar una forma sobrecargada del método que nos permite especificar que sean lamadas cliente-servidor asíncronas, y que añade dos parçametros más a los cuatro que acabamos de ver:

  • Función JavaScript para errores: el nombre de una función JavaScript que se llamará de forma automática en caso de producirse cualquier error en la llamada al servidor. Toma los mismos parámetros que en el caso de la función JavaScript de retorno.
  • ¿La llamada es asíncrona?: si ponemos true será asíncrona (AJAX) y si ponemos false (valor por defecto) será síncrona.

Personalmente esta es la versión del método que uso generalmente y la que recomiendo.

Recapitulemos

Aunque todo lo explicado puede resultar un tanto lioso en realidad es muy fácil. Si lo exponemos de nuevo punto por punto lo veremos con más claridad y en el próximo post veremos un caso práctico de aplicación que lo acabará por aclarar:

  1. Definimos en el código HTML de nuestra página una función JavaScript en el cliente, que toma como parámetros una cadena con los resultados de la llamada al servidor que queremos realizar, y una variable de contexto (normalmente no utilizada). Opcionalmente
  2. Definimos un atributo para un control que, respondiendo a un evento de HTML, hará una llamada al servidor que será la que nos devuelva los resultados. Puede ser un clic, un cambio de selección, etc... Para saber qué código JavaScript debemos usar para la llamada usamos el método GetCallbackEventReference.
  3. En el servidor en uno de nuestros controles o en la propia página implementamos la interfaz ICallbackEventHandler cuyos métodos serán llamados automáticamente cuando se realice la llamada desde el cliente al servidor.

¡Listo!. Como veremos esto es más fácil de lo que parece.

Sólo dos notas antes de terminar por hoy:

· Esta técnica funciona con cualquier navegador moderno como fireFox, Safari u Opera, no sólo con Internet Explorer, como afirman algunos artículos por ahí.

· Para distinguir si una llamada al servidor (por ejemplo en Page_Load, que obviamente se llama siempre junto con los demás eventos de la página) se corresponde con una llamada AJAX cliente.servidor, la clase Page define una propiedad IsCallback que permite distinguirlo y funciona del mismo modo que el IsPostBack al que todos estamos acostumbrados.

En el próximo post haremos un ejemplo completo y proporcionaré el código fuente, dejando el tema completamente cerrado. Hasta pronto.

José Manuel Alarcón
Banner

Comentarios (1) -

Hola:

Pues con esas pistas no sé qué decirte. Depende de cómo lo hayas hecho, pero por el mero hecho de ser un callback no debería fallar.
Habría que ver el código.

Saludos

JM.

Responder

Agregar comentario