Colabora .NET |
El Poder de AJAX en Tiempo Real
Fecha: 04/Jul/2006 (23-06-06)
|
El Poder de AJAX en Tiempo Real Por Harvey Triana Introducción AJAX es una estrategia de
programación creada para evitar en lo posible el “postback”, y mejorar tanto
la experiencia final del usuario como el desempeño de la aplicación Web. AJAX, que es el acrónimo para
JavaScript asíncrono y XML, pone de manifiesto una pronunciada evolución de
aplicaciones Web basadas en ASP.NET 2.0. Es tan
atractivo el asunto que me hizo mirar hacia tecnologías .NET nuevamente y a
usar fuertemente ASP.NET 2.0 en mis proyectos. No obstante, el estado del
arte de usar AJAX esta en ATLAS, el cual es un framework de alto nivel que simplifica notablemente AJAX a los
desarrolladores Web que usan ASP.NET 2.0. No obstante AJAX exige que un
programador de .NET necesite alta pericia para poner en real producción el
asunto. AJAX rompe un poco un principio
que reza: “el código y la presentación van separados”. No obstante Atlas
hace posible que esta promesa sea más aproximada a la verdad. En general, la
principal dificultad de AJAX radica en que el desarrollador esta obligado a
escribir código JavaScript del lado
del cliente y a manejar perfectamente el esquema de Callbacks disponible en ASP.NET 2.0, cuestiones que no son
simples, y están lejos de una intención RAD. Cuando recién empiezas a usar
ATLAS, y lees la documentación, quizás encuentres que conceptualmente es
difícil, analíticamente disfraza su complejidad ¿Por qué? Si revisamos un
poco la raíz del asunto, es decir AJAX, vamos a comprender mucho a ATLAS. Por
supuesto, después de asimilar el marco teórico de AJAX, ATLAS nos va a
parecer natural, y hasta sencillo de usar. En general, pongo de manifiesto
que un sitio Web basado en callbacks es una odisea técnica en la que no
deberíamos abarcarnos. Para eso disponemos de ATLAS. No obstante, en ciertos
casos AJAX podría ser necesario, el caso particular lo expongo al final del
artículo. En Tiempo Real En algunos de mis proyectos de
ingeniería, un requisito es que el software opere en tiempo real. Algunos se
preguntan que es exactamente “ejecutar en tiempo real”. Es fácil de
comprender si se hace la analogía con la televisión. Un partido de fútbol en
directo, es en tiempo real, es decir, la respuesta se obtiene en el tiempo
actual y no a posteriori. Un ejemplo de software en tiempo real es el
siguiente: A otro lado del mundo se desea monitorear una curva de
comportamiento de la perforación de un pozo petrolero. En principio, tenemos
que ir hasta un servidor Web instalado en la localización del pozo, extraer
un conjunto de datos generados en tiempo real, generar un gráfico y enviarlo
a los clientes vía Web. Si se hiciera usando “postback”, los clientes verían
una fea imagen parpadeante. El problema se puede solucionar al usar un
control ActiveX grueso del lado del cliente, el cual solo recoge los datos
vía TCP/IP, y genera el grafico en el PC del cliente. Como sabrán, las
limitaciones de ActiveX en la web son notables, el mantenimiento de tales
objetos se dificulta cuando se quiere hacer una mejora o modificar un
comportamiento. En la mayoría de los casos se tendrá que hacer una reinstalación en el cliente, cosa que para
los usuarios normales es una molestia
y a veces una frustración para ambas partes. La solución ideal
consiste en que la parte difícil, llámese regla de negocios, ejecute en el
servidor Web, y que el cliente, muy ligero, reciba los datos sin “postback”. Cualquier
mantenimiento de los objetos favorece a todos los clientes. En resumen AJAX,
y el poder de ATLAS, suministra esta característica. Para operar en tiempo real requerimos
de eventos en tiempo, es decir de objetos “temporizadores”. Cuando operamos
vía Web, tenemos dos situaciones, el Tiempo del Cliente, y el Tiempo de
Servidor. Por supuesto, en estas dos situaciones los tiempos serán diferentes
por la diferencia horaria, siendo muy poco notable cuando nos encontramos en
la misma latitud. Así pues, me voy a centrar en
mostrar la base de un sistema en tiempo real. ¿Qué tal una pagina que muestre
simultáneamente el tiempo del cliente, y el tiempo del Servidor? Y, por
supuesto, no queremos postback. Voy a exponer la solución del
problema de manera ascendente, es decir, de lo simple a lo complejo. Esto me
parece más didáctico y útil. Seguiré estos pasos:
·
Leer Tiempo del Cliente
·
Leer el Tiempo del Servidor con Postback
·
Leer el Tiempo del Servidor y del Cliente usando
Callback
·
Leer el Tiempo del Servidor y del Cliente usando
Atlas Leer Tiempo del Cliente Para obtener el tiempo del
cliente necesitamos una función JavaScript. El Script que escribí retorna el tiempo en formato “dd/mm/yy hh:mm:ss” que es general y
conveniente para usar en bases de datos de Microsoft como MS SQL Server y MS
Access. Para reutilizar el código, es conveniente guardar el código
JavaScript en un archivo JScript y agregarlo al proyecto como un nuevo ítem
de “Archivo JScript”. En este ejemplo el archivo se llama “ClientTime.js”. He
aquí el código:
Para programar un evento de
temporizador del lado del cliente en una pagina web, JavaScript suministra un
esquema sencillo, se activa un procedimiento invocando el método setTimeout del objeto window, el cual usa como parámetros el
nombre de la función que se va a llamar, y el tiempo en milisegundos de
espera para hacer la llamada. Hacemos la primera llamada desde el evento de
carga de la página, normalmente “body
onload” o un “Page Load”. Para
hacer el temporizador continuo, la función que se invoca en setTimeout debe llamar nuevamente a setTimeout. Por ultimo si queremos mostrar el resultado
en la pagina, desde unas líneas escribimos en un control del lado del
cliente. En el siguiente ejemplo el tiempo del cliente se muestra en una caja
de texto de html de nombre “txtClientTime”. Finalmente el código de la pagina es el
siguiente:
Siempre que se quieran datos
del cliente es necesario recurrir a código del lado del cliente. Se usa solo
JavaScript para aumentar compatibilidad para los diferentes visualizadores. Hasta acá no hemos visto nada
interesante. Solo mostré como programar un temporizador del lado del
cliente en una página Web. Leer Tiempo del Servidor con Postback Leer el tiempo del servidor en
un postback no requiere mucha
discusión. Solo necesitamos un control asp
con postback. En el código del lado del servidor leemos el retorno de la
función DateTime.Now(). Si queremos mostrarla en un control
la asignamos directamente. Ejemplo, usamos un botón btnServerTime y una caja de texto txtServerTime:
Leer el tiempo del servidor
con postback seria útil cuando no se requiere un proceso continuo, es decir,
el proceso se ejecuta muy eventualmente o por acción del usuario. Leer Tiempo del Servidor usando
Callback Usando callbacks podemos desde
el código del servidor leer el resultado de una función JavaScript. Elaborar
una respuesta, y con este resultado actualizar la pagina ASP sin postback.
Básicamente, un callback es un dialogo entre el código JavaScript de la página
y el código .NET del servidor. Para usar un Callback de
ASP.NET 2.0 necesitamos usar el siguiente esquema, siendo el mismo para
cualquier solución:
1.
Implementar la interfaz ICallbackEventHandler
2.
Configurar las retrollamadas en Page_Load
3.
Escribir respuesta en RiseCallbackEvent, proceso de negocios
4.
Enviar respuesta en GetCallbackResult
5.
Escribir respuesta en la página El problema que estoy
exponiendo en este articulo puede ser muy didáctico
para mostrar una implementación de un callback. Si desea seguir el ejemplo
paso a paso, en un sitio Web de ASP.NET 2.0 cualesquiera, cree un Web Form de nombre “DiferenciaHoraria”, - mantenga el
código en un archivo separado. Añada este código a la página.
Note que se invoca una función
JavaScript de nombre callServerTask la cual no existe en la página. La función callServerTask será escrita por el
código del lado del servidor. 1. Implementar la interfaz ICallbackEventHandler La
implemantacion de la interfaz ICallbackEventHandler
capacita a la página Web a usar Callbacks de ASP.NET 2.0. La interfaz habilita los eventos: RaiseCallbackResult y GetCallbackResult los cuales se
configuran para usar dos subrutinas de JavaScript, una que llama a RaiseCallbackResult
y la otra que toma una respuesta elaborada enviada por GetCallbackResult. Implementamos la intefaz al heredar de ICallbackEventHandler
en C#, o al agregar la directiva “Implements ICallbackEventHandler” en
VB.NET. Sugiero que
siempre se agregue la variable a nivel de modulo de nombre “_callbackResult”
para C# o “m_CallbackResult” para
VB.NET. Aunque el nombre es a su libre albedrio, podemos generalizar un
nombre para simplicar el asunto. Así, el código de GetCallbackResult() puede ser el mismo en cada aplicación que use
callbacks, solo se hace un retorno
de m_CallbackResult. A modo de
información dire que esto es lo que se usa en la ultima liberacion de VS2005. 2. Configurar las retrollamadas en Page_Load La configuracion
del callback se hace en el evento Page_Load.
Aca debemos generar una linea de codigo que se agregará dinamicamente a la
página y es la encargada del callback. ASP.NET facilita esto a traves del
metodo GetCallbackEventReference. Atención a los argumentos de GetCallbackEventReference. El
primero es el objeto contenedor, es decir, this para C#, y Me para
VB.NET. El segundo, clientTime('') en el ejemplo, es argumento el
cual será pasado a RaiseCallbackEvent. Este
argumento puede variar según el contexto de la aplicación. El tercer
argumento, putCallbackResult, es la
funcion que se invocará desde GetCallbackResult
pasando m_CallbackResult como argumento
de putCallbackResult, es decir, se pasan datos del codigo del servidor al
código del cliente. Los demas
argumentos son opcionales. En particular, es conveniente agregar una funcion
que reporte un posible error en el callback. He generalizado este nombre a clientErrorCallback. Al final de Page_Load usamos RegisterClientScriptBlock el cual es el metodo encargado de
enviar la fuente de texto script a la pagina. Normalmente
en al final de Page_Load agegamos
un atributo a un control para habilitar un evento que será el responsable de
llamar la funcion callServerTask().
En este caso no es necesario ya que callServerTask()
es llamada desde la function timerEvent(). El resultado
de GetCallbackEventReference se puede visualizar en el código de la pagina
leida por el visualizador de internet. Realmente la complejidad no es algo
que nos deba preocupar. He aquí el código generado a manera de ilustración:
3. Escribir respuesta en RiseCallbackEvent RiseCallbackEvent es una
funcion que se invoca desde la página al servidor sin postbak. Un script de
JavaScript coloca el argumento eventArgument
de RiseCallbackEvent el cual es una
cadena de texto de JavaScript. En RiseCallbackEvent
procesamos esta cadena para generar una respuesta HTML. En una aplicación de
produccion, eventArgument suele
contener el valor de una clave para filtrar una vista de datos. En seguida
procesamos eventArgument, es decir
hacemos lo que en ingles se conoce como parsing, que no es más que extraer
informacion de una cadena de texto. Luego elaboramos una respueta HTML. Siga
el ejemplo para dislumbrar los metodos pertinentes para elaboral tal
respuesta. La complejidad no va más alla de lo expuesto en el ejemplo. 4. Enviar respuesta en GetCallbackResult La cadena o
fuente HTML generada como respuesta es asignada a m_CallbackResult, la
cual asu vez es retornada
inmediatamente a la pagina a traves de GetCallbackResult. 5. Escribir respuesta en la página La pagina ahora
tiene el resultado del callback en la variable m_CallbackResult que ahora es un argumento de putCallbackResult, y este escribe la
division 'div_CallbackResult'. El
nombre 'div_CallbackResult' tambien
es definido por el programados. Como he venido comentando, si usamos un
nombre generalizado como 'div_CallbackResult' podemos hacer más simple la
programacion AJAX. He usado una etiqueta DIV la cual encierra toda la
respuesta HTML. No necesariamente tiene que ser una etiqueta DIV, puede ser
cualquier objeto HTML. Solo se trata de generalizar para simplificar. Para hacer simplificar código
en la página las funciones putCallbackResult y clientErrorCallback se pueden colocar en un
archivo JScript e incrustar en la página con una directiva src. El archivo será un ítem más de la
aplicación Web. He llamado a este archivo “CallBackComplement.js”. He aquí su código:
Otra ventaja de aislar el
código JavaScript de la página es el espacio que se gana para un código más
elaborado según la necesidad del programador. Finalmente,
el resultado de los 5 pasos afin al ejemplo expuesto se resume en el
siguiente código:
Finalmente, si ejecutamos esta
página en el entorno de desarrollo veremos la misma hora. Si la publicamos en
la web una persona que viste nuestra página verá su diferencia horaria con
respecto al servidor. Leer Tiempo del Servidor y del Cliente
usando Atlas Atlas simplifica notablemente
el código AJAX y lo extiende a un nivel sorprendente. No obstante, si deseas
convertirte en un programador Atlas hay una curva de aprendizaje. En
particular el XML-Script que usa Atlas para simplificar muchas acciones del
lado del cliente es un nuevo conjunto de reglas que hay que aprender.
Recomiendo se siga la documentación de Atlas para dominar el asunto. Si no dispone de Atlas debe
seguir las instrucciones para instalación de la página oficial: http://atlas.asp.net/ El problema del articulo se puede enfocar desde una perspectiva
relativamente simple: Usando controles del lado del servidor de Atlas. Es
posible implementar el asunto usando un servicio Web pero extiende la
complejidad de este problema en particular sin necesidad. Tiempo del Servidor Usando Controles de Atlas Para resolver el problema
bastan tres controles del servidor de Atlas: atlas:ScriptManager, atlas:Update Panel y atlas:Timer. atlas:ScriptManager. Es requerido en toda página potenciada con Atlas.
Carga los objetos JavaScript del ensamblado Microsoft.Web.Atlas.dll. En las
versiones preliminares de Atlas, era necesario cargar varios archivos JScript. Esto ya no es necesario. atlas:UpdatePanel. Es un contenedor especializado en manejar el
refresco parcial de la página y evitar el efecto postback. El panel se
actualiza en acción a un disparador, atlas:Trigger
que no es mas que otro elemento el cual tiene codificado la acción, ya sea un
evento o el cambio de una propiedad de un control de la página que hará que
se actualice el contenido del panel de Atlas. atlas:TimerControl. Es un control de Atlas que suministra un objeto temporizador
entre la página web y el servidor. Anteriormente, un temporizador del lado
del servidor en paginas ASP.NET era una cuestión inverosímil o demasiado laboriosa. Nota. Cuando has trabajado
Atlas versión abril de 2006, descubres que la manera fácil es escribir
directamente en la página HTML, y seguir el IntelliSense. Imagino que para
las versiones futuras de ASP.NET Atlas hará parte de todo el arsenal de
herramientas en el IDE. Veamos como combinan estos
controles para dar solución al problema de este articulo:
La respuesta del evento
temporizador se recibe en el servidor. Sorprendentemente, se puede asumir el
temporizador casi de la misma forma que en una aplicación Windows.
Ahora, si bajo este esquema de
Atlas quisiéramos leer el tiempo del cliente para hacer algo con el, por
ejemplo reportar la hora de la visita de un cliente, la cuestión no es tan
simple. No obstante el código que documento a continuación lo hace posible. Primero, complementamos el
código HTML anterior con unos Scripts:
Para leer el tiempo del
cliente tengo que incluir nuevamente ClientTime.js ¿Queda
demostrado que usar la directiva src
es la manera eficaz de reutilizar codigo de JavaScript? Sin duda. La función PageRequestManagerPropertyChanged habilita a la pagina para que despues de un PostBack, parcial o completo, se llame
una funcion del código del cliente. En este caso llamo a showClientTime la cual me actualiza el dato deseado. Una funcion
como PageRequestManagerPropertyChanged usa
sintaxis exclusivo de Atlas. Otro interesante detalle acá
es que agregue un cuadro de texto HTML con un el atributo “runat=Server”. Esto me capacita para
leer el valor del control HTML desde el código del servidor. Por ejemplo:
Conclusiones AJAX puro, basado en Callbacks
de ASP.NET 2.0 no es simple. Se deben seguir varias reglas para cumplir un
objetivo. No obstante, si centramos una estrategia de nombres podemos
simplificar la complejidad. Realmente, si queremos afirmar que programamos
“AJAX” deberíamos entender la teoría del asunto. Quizás haya problemas que
aun no cubra Atlas. He encontrado que manejar gráficos puede ser mas eficiente con Callbacks, aunque por la fuerte
evolución de AJAX, prefiero no asumir esta afirmación formalmente. Atlas brinda un modelo de
programación muy flexible, no obstante existe una curva de aprendizaje
conceptual no muy suave. Si se desea cuestiones avanzadas vamos a tener que
recurrir al duro JavaScript. Quedan sentada la base para un
sistema Web que ejecute en tiempo real y con grandes posibilidades de una
interfaz de usuario rica. Referencias 1. AJAX un nuevo acercamiento
a Aplicaciones Web http://www.uberbin.net/archivos/internet/ajax-un-nuevo-acercamiento-a-aplicaciones-web.php 2. Implementing Client Callbacks Without Postbacks
in ASP.NET Web Pages http://msdn2.microsoft.com/en-us/library/ms178208.aspx 3. ASP.NET “Atlas” Código del Articulo: http://200.118.112.230/DV/articles/El_Poder_de_AJAX_en_Tiempo_Real.zip |