Colabora .NET

El Poder de AJAX en Tiempo Real

 

Fecha: 04/Jul/2006 (23-06-06)
Autor: Harvey Triana

 


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:

 

Script 1: Tiempo del Cliente en JavaScript. Archivo ClientTime.js

 

// JScript File

function clientTime()

{

    var t = new Date();

    return (

      char2(t.getDate()) + "/" +

char2(t.getMonth() + 1) + "/" +

String(t.getYear()).substring(4,2) + " " +

char2(t.getHours()) + ":" +

char2(t.getMinutes()) + ":" +

char2(t.getSeconds()));

}

function char2(v)

{

    if ((v >= 0) && (v <= 9))

       return "0" + v;

    else

       return v;

}

 

 

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:

 

Código HTML de TiempoDelCliente.aspx

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>Tiempo del Cliente</title>

</head>

<body onload="window.setTimeout('timerEvent()',1500);">

    <form id="form1" runat="server">

    <div>

    <span>Tu Hora: </span>

    <input id="txtClientTime" type="text" style="width: 200px" />

    </div>

    </form>

</body>

</html>

 

<script type="text/javascript" src="ClientTime.js"></script>

<script type="text/javascript">

// activando un "Timer"

function timerEvent()

{

showClientTime();

    // hace continuo el Timer

window.setTimeout("timerEvent()",1000);

}

function showClientTime()

{

    t = clientTime();

    var r = document.getElementById("txtClientTime");

    r.value = t;

}

</script> 

 

 

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:

 

C#: Leer Tiempo del Servidor con Postback

 

    protected void btnServerTime_Click(object sender, EventArgs e)

    {

        this.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss");

    }

 

VB.NET: Leer Tiempo del Servidor con Postback

 

    Protected Sub btnServerTime_Click( _

        ByVal sender As Object, _

        ByVal e As System.EventArgs) Handles btnServerTime.Click

 

        Me.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss")

    End Sub

 

 

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.

 

 

Codigo de la página DiferenciaHoraria.aspx, usando Callback

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Diferencia Horaria</title>

</head>

<body onload="window.setTimeout('timerEvent()',1500);">

    <form id="form1" runat="server">

    <div>

        <h2>Diferencia Horaria</h2>

        <hr />

        <div id="div_CallbackResult">

        <asp:TextBox ID="txtClientTime" runat="server" />

        <br />

        <asp:TextBox ID="txtServerTime" runat="server" />

        </div>

        <hr />

    </div>

    </form>

</body>

</html>

<script type="text/javascript" src="ClientTime.js"></script>

<script type="text/javascript" src="CallbackComplement.js"></script>

<script type="text/javascript">

function timerEvent()

{

callServerTask();

window.setTimeout("timerEvent()",1500);

  return false;

}

</script>

 

 

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:

 

 

Código JavaScript generado por GetCallbackEventReference

 

function callServerTask()

   { WebForm_DoCallback('__Page',clientTime(''),

                        putCallbackResult,null,clientErrorCallback,true);

   }

 

 

 

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:

 

 

Código de CallBackComplement.js

 

// JScript File

function putCallbackResult( callbackResult ) 

{    

    var info = document.getElementById('div_CallbackResult');

info.innerHTML = callbackResult;

}

function clientErrorCallback( error, context ) 

{    

    alert('Callback failed! ' + error); 

}

 

 

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:

 

C#: Codigo de DiferenciaHoraria_CS.aspx

 

using System;

using System.Web.UI;

using System.Text;

using System.IO;

 

public partial class DiferenciaHoraria_CS : Page, ICallbackEventHandler

{

    private string _callbackResult;

 

    protected void Page_Load(object sender, EventArgs e)

    {

        StringBuilder s = new StringBuilder();

        string er;

        //  configura los llamados a RaiseCallbackEvent y GetCallbackResult

        er = ClientScript.GetCallbackEventReference(

             this, "clientTime('')", "putCallbackResult",

             "null", "clientErrorCallback", true);

 

        //  funcion que llama a RaiseCallbackEvent

s.Append(" function callServerTask() { ");

s.Append((er + ";"));

s.Append(" } ");

 

        //  inserta el script en la pgina

        Page.ClientScript.RegisterClientScriptBlock(

             this.GetType(), "callServerTask", s.ToString(), true);

       

        //  NOTA:

        //  La función callServerTask() es llamada desde la function timerEvent() }

   

    public void RaiseCallbackEvent(string eventArgument)

    {

        const string DT = "dd/MM/yy hh:mm:ss tt";

   

        StringWriter sr = new StringWriter();

        HtmlTextWriter htm = new HtmlTextWriter(sr);

       

        //  todos los controles modificados aca debe estar en la division

        //  <div id="div_CallbackResult">

        //  tiempo del cliente

        this.txtClientTime.Text = "Tu Tiempo: " +

                                  Convert.ToDateTime(eventArgument).ToString(DT);

        this.txtClientTime.RenderControl(htm);

htm.Flush();

        //  html extra

htm.Write("<br />");

        //  tiempo del servidor

        this.txtServerTime.Text = "Mi Tiempo: " + DateTime.Now.ToString(DT);

        txtServerTime.RenderControl(htm);

htm.Flush();

        //  retorna una fuente html a la funcin putCallbackResult()

        _callbackResult = sr.ToString();

    }

 

    public string GetCallbackResult()

    {

        //  ésta variable es pasada al argumento de putCallbackResult

        return _callbackResult;

    }

}

 

VB.NET: Codigo de DiferenciaHoraria_CS.aspx

 

Imports System.Web.UI

Imports System.Text

Imports System.IO

 

Partial Class DiferenciaHoraria_VB

    Inherits Page

    Implements ICallbackEventHandler

 

    Private m_CallbackResult As String

 

    Protected Sub Page_Load( _

        ByVal sender As Object, _

        ByVal e As System.EventArgs) Handles Me.Load

 

        Dim s As New StringBuilder

        Dim er As String

 

        ' configura los llamados a RaiseCallbackEvent y GetCallbackResult

        er = ClientScript.GetCallbackEventReference( _

Me, _

"clientTime('')", _

"putCallbackResult", _

"null", _

"clientErrorCallback", _

True)

        ' funcion que llama a RaiseCallbackEvent

s.Append(" function callServerTask() { ")

s.Append(er & ";")

s.Append(" } ")

 

        ' inserta el script en la página

        Page.ClientScript.RegisterClientScriptBlock( _

                          GetType(String), "callServerTask", s.ToString, True)

        ' NOTA:

        ' El callback es llamado desde un timer del lado del cliente,

        ' la function timerEvent()

    End Sub

 

    Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _

        Implements ICallbackEventHandler.RaiseCallbackEvent

 

        Const DT As String = "dd/MM/yy hh:mm:ss tt"

 

        ' elabora una respuesta HTML

        Dim sr As New StringWriter()

        Dim htm As New HtmlTextWriter(sr)

 

        ' todos los controles modificados aca debe estar en la division

        ' <div id="div_CallbackResult">

        ' tiempo del cliente

        Me.txtClientTime.Text = "Tu Tiempo: " & _

                         CType(eventArgument, Date).ToString(DT)

        Me.txtClientTime.RenderControl(htm)

        htm.Flush()

        ' html extra

htm.Write("<br />")

        ' tiempo del servidor

        txtServerTime.Text = "Mi Tiempo: " & Date.Now().ToString(DT)

        txtServerTime.RenderControl(htm)

htm.Flush()

 

        ' La función callServerTask() es llamada desde la function timerEvent()

        m_CallbackResult = sr.ToString

    End Sub

 

    Public Function GetCallbackResult() As String _

        Implements ICallbackEventHandler.GetCallbackResult

        ' ésta variable es pasada al argumento de putCallbackResult

        Return m_CallbackResult

    End Function

End Class

 

 

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:

 

C#: Codigo de DiferenciaHoraria_Atlas_CS.aspx (es mismo para DiferenciaHoraria_Atlas_VB.aspx)

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Tiempo del Servidor con Atlas</title>

</head>

<body>

    <form id="form1" runat="server">

        <h2>Tiempo del Servidor con Atlas</h2><hr />

        <div>

            <atlas:ScriptManager runat="server" ID="sm"

                                 EnablePartialRendering="true" />

            <atlas:TimerControl runat="server" ID="tmrServerTime"

                                Interval="1500" OnTick="tmrServerTime_Tick" />

            <atlas:UpdatePanel ID="up1" runat="server">

            <Triggers>

            <atlas:ControlEventTrigger ControlID="tmrServerTime"

                                    EventName="Tick" /> 

            </Triggers>

            <ContentTemplate>

            <asp:TextBox ID="txtServerTime" runat="server" Width="220px" />

            </ContentTemplate>

            </atlas:UpdatePanel>

            </div>

            <div>

            <input id="txtClientTime" type="text" style="width: 220px"

                   runat="server" />

            </div><hr />

    </form>

</body>

</html>

 

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.

 

C#: DiferenciaHoraria_Atlas_CS.aspx.cs

 

    protected void tmrServerTime_Tick(object sender, EventArgs e)

    {

        this.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss");

    }

 

VB.NET: DiferenciaHoraria_Atlas_VB.vb

 

    Protected Sub tmrServerTime_Tick ( _

        ByVal sender As Object, _

        ByVal e As System.EventArgs) Handles tmrServerTime.Tick

 

        Me.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss")

    End Sub

 

 

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:

 

Complemento a código Atlas para leer el tiempo del cliente

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Tiempo del Servidor con Atlas</title>

</head>

<body>

    <form id="form1" runat="server">

        <h2>Tiempo del Servidor con Atlas</h2><hr />

        <div>

            <atlas:ScriptManager runat="server" ID="sm"

                                 EnablePartialRendering="true" />

            <atlas:TimerControl runat="server" ID="tmrServerTime"

                                Interval="1500" OnTick="tmrServerTime_Tick" />

            <atlas:UpdatePanel ID="up1" runat="server">

            <Triggers>

            <atlas:ControlEventTrigger ControlID="tmrServerTime"

                                       EventName="Tick" /> 

            </Triggers>

            <ContentTemplate>

            <asp:TextBox ID="txtServerTime" runat="server" Width="220px" />

            </ContentTemplate>

            </atlas:UpdatePanel>

            </div>

            <div>

            <input id="txtClientTime" type="text" style="width: 220px"

                   runat="server" />

            </div><hr />

    </form>

</body>

</html>

<script type="text/javascript" src="ClientTime.js"></script>

<script type="text/javascript">

function showClientTime()

{

    //run after postback

    t = clientTime();

    var r = document.getElementById("txtClientTime");

    r.value = t;

}

   

// tip source: http://forums.asp.net/thread/1274000.aspx

function PageRequestManagerPropertyChanged(sender, args)

{

    if (args.get_propertyName() == "inPostBack")

    {

        if (!$object("_PageRequestManager").get_inPostBack())

showClientTime();

    }

}

function pageLoad()

{

    $object("_PageRequestManager").propertyChanged.add(

            PageRequestManagerPropertyChanged);

}

</script>

 

 

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:

 

C#: DiferenciaHoraria_Atlas_CS.aspx.cs

 

    protected void tmrServerTime_Tick(object sender, EventArgs e)

    {

        this.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss");

       

        // podemos leer el tiempo del cliente en virtud de runat=server

        string ClientTime = this.txtClientTime.Value; 

    }

 

VB.NET: DiferenciaHoraria_Atlas_VB.aspx.vb

 

   Protected Sub tmrServerTime_Tick ( _

       ByVal sender As Object, _

       ByVal e As System.EventArgs) Handles tmrServerTime.Tick

 

       Me.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss")

      

        // podemos leer el tiempo del cliente en virtud de runat=server

       Dim ClientTime As String = Me.txtClientTime.Value

    End Sub

 

 

 

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”

http://atlas.asp.net/

 

Código del Articulo:

http://200.118.112.230/DV/articles/El_Poder_de_AJAX_en_Tiempo_Real.zip

 

 


ir al índice principal del Guille