Y dado que AJAX cubre la parte cliente, es obvio pensar que el complemento ideal en el lado del servidor son los servicios web, dada la coincidencia en el lenguaje de intercambio utilizado (XML), y la facilidad con que se desarrollan, despliegan y comunican.
El framework publicado por Microsoft hace unos meses, llamado ATLAS durante su periodo de desarrollo, facilita enormemente la tarea de inclusión de características AJAX en aplicaciones ASP.NET. El sistema completo se entrega en dos paquetes:
- ASP.NET 2.0 AJAX Extensions, que es el componente base que establece la infraestructura para la utilización de esta tecnología sobre páginas asp.net. El ejemplo que desarrollaremos en este post se basa en estos componentes.
- ASP.NET AJAX Control Toolkit, que incluye un buen número de componentes visuales y no visuales que hacen uso de la infraestructura AJAX a todo trapo. Algunos son una maravilla, y además es un proyecto compartido con la comunidad bajo licencia MsPL.
A lo largo de este post vamos a desarrollar paso a paso un ejemplo completo de interacción de un cliente con un servidor utilizando AJAX. El proyecto será bien simple, pero creo que suficientemente ilustrativo: crearemos con VS2005 una página web con un botón, cuya pulsación provocará que se obtenga desde el servidor un mensaje, que será mostrado por pantalla, ¡y todo ello sin provocar recarga de la página!
En primer lugar, abrimos Visual Studio 2005 y creamos un proyecto. Para facilitar la tarea, la instalación del framework AJAX habrá incluido una plantilla llamada "ASP.NET Ajax-Enabled web application", que es la que debemos elegir. De esta forma, se añadirán las referencias necesarias para que todo funcione.
Hecho esto, el entorno habrá creado una página "default.aspx" a la que simplemente habrá añadido un control de servidor de tipo ScriptManager. Este control es el que hace la magia, como veremos más adelante, asilándonos de la complejidad real que tiene una comunicación asíncrona con el servidor como la que vamos a realizar.
A continuación añadimos al proyecto un servicio web, con lo que Visual Studio generará un archivo estándar con un método, el consabido HelloWorld(), que devuelve un string con el mensaje de saludo.
Pues bien, aquí es donde empieza la fiesta. En primer lugar, vamos a modificar ligeramente este método para que devuelva mensajes diferentes y podamos comprobar, a posteriori, el funcionamiento del sistema.
Por ejemplo, añadiremos al saludo la hora actual del servidor:
[WebMethod]
public string HelloWorld()
{
return "Hola a todos desde el servidor, son las " +
DateTime.Now.ToString("hh:mm:ss");
}
Además, introducimos justo antes de la declaración de la clase, en las primeras líneas del archivo, la declaración del atributo [ScriptService] de la siguiente forma:
...
[System.Web.Script.Services.ScriptService] // ¡Necesario!
public class ServicioWeb : System.Web.Services.WebService
...
De esta forma, indicamos que la clase contiene servicios que serán accedidos desde el cliente utilizando scripting (javascript). Y con esto, hemos acabado con la parte de servidor, pasamos ahora a ver el lado cliente, cómo utilizamos este servicio.
En primer lugar, añadimos dos controles a la página web (default.aspx), un botón que provocará la llamada al servidor, y una etiqueta donde iremos mostrando los resultados. El código es el siguiente:
<input id="Button1" type="button" value="¡Pulsa!" onclick="llamar();" />
<br />
<strong>Mensajes obtenidos:</strong><br />
<label id="lblMensajes"></label>
Podemos observar, ninguno de los controles introducidos son de servidor, es decir, no incluyen un runat="server". Es lógico, pues toda la interacción la vamos a realizar en cliente.
Además, vemos que el botón incluye un controlador del evento OnClick, la función llamar() de javascript. La idea es que esta función obtenga del servidor el mensaje de saludo correspondiente, y vaya añadiéndolo al contenido de la etiqueta. Basta con añadir el siguiente código a la página, dentro del correspondiente tag <script>:
function llamar()
{
AJAXWSDemo.ServicioWeb.HelloWorld(OnLlamadaFinalizada);
}
Aquí hay varios aspectos a destacar. En primer lugar, que estamos llamando al método HelloWorld desde script (en cliente) indicando la ruta completa hasta el mismo, es decir, el namespace (AJAXWSDemo) y la clase donde se encuentra (ServicioWeb). ¿Y cómo es posible esto? Por obra y gracia del control ScriptManager, que ya vimos anteriormente, que es quien ha encargado de generar un envoltorio (wrapper) apropiado para los servicios a los que vamos a acceder desde el cliente, haciéndolo así de sencillo.
Sin embargo, para que ScriptManager sea consciente de los servicios que debe gestionar, hay que indicárselo expresamente, incluyendo el siguiente código dentro del propio control. Creo que se entiende directamente, lo que hace es crear una referencia a la url que contiene los métodos a los que vamos a llamar:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="ServicioWeb.asmx" />
</Services>
</asp:ScriptManager>
...
Hecho este inciso, continuamos ahora comentando la función llamar(). Por otra parte, vemos un parámetro extraño en la llamada al método, "OnLlamadaFinalizada". Esto es así porque las llamadas a servicios deben incluir un parámetro adicional que es la función a la que el sistema notificará que ha completado la invocación al método. Hemos de recordar que las llamadas son, por defecto, asíncronas; esto quiere decir que el sistema no espera a su finalización, la llamada se realiza en background y cuando son completadas el control se transfiere a la función de notificación que hayamos elegido.
A esta misma función de retorno le llegará un parámetro, el valor devuelto desde el servicio web. Por este motivo, no es necesario obtener el valor de retorno en el momento de invocación del método remoto.
El código para la función de retorno es, en nuestro caso,
function OnLlamadaFinalizada(resultado)
{
var etiqueta = $get("lblMensajes");
etiqueta.innerHTML += resultado + "<br />";
}
En este caso, destacamos varios aspectos también. En primer lugar, como hemos comentado anteriormente, el parámetro que recibe la función es el retorno del servicio web invocado.
También puede que llame la atención la expresión $get("lblMensajes"). Se trata de un atajo que evita tener que introducir el código "document.getElementById(...)" necesario para obtener referencias a un control de la página.
El resultado final se puede ver en la siguiente captura, demostrando, además, que funciona perfectamente en Firefox:
Y para los perezosos, he dejado en http://www.snapdrive.net/files/415885/AJAXWSDemo.zip el proyecto VS2005, para que podáis jugar con él sin necesidad de teclear nada.
Actualización: si has leído hasta aquí, es posible que también te interese este otro post donde se muestra otra forma de comunicarse con el servidor utilizando ASP.NET 2.0 AJAX.
Publicado por José M. Aguilar a las 3:41 p. m.
Etiquetas: ajax, asp.net, c#, microsoft, programación
6 Comentarios:
Un artículo por demás interesante y muy bien explicado, muchas gracias. Saludos desde Argentina.
Excelente artículo para leer y aprender.
Muchas gracias por escribirlo y publicarlo.
Un saludo desde Buenos Aires, Argentina.
Victor
Excelente muy bien explicado, faltaria algo similar como podriamos hacerlo con una BD (SQL, ACCESS)
Gracias.
El ejemplo solo funciona para AJAX Web Sites ASP.NET y no funciona para AJAX Web Applications ASP.NET.
Faltaria un ejemplo utilizando webapplications y ajax.
Saludos
Guillermo Galvagni
Hola Jose Maria
Buen aporte, gracias
Podrías decirme como consumir un web service(1) desde otro web service(2) (WCF) me comentan que por proxy se podria
el WS(2) seria una mascara para mandar llamar al (WS1)
Saludos
Hola,
consumir un web service (WS1) desde otro web service (WS2) no es muy distinto a consumir WS1 desde cualquier otro tipo de sistema basado en .NET.
Observa que simplemente WS2 actuaría como cliente de WS1. En el primero tendrías que usar componentes cliente de acceso a servicios web, como los proxies autogenerados por Visual Studio.
Así, en el interior del código que procesa las llamadas a WS2 encontrarías a su vez las llamadas a WS1.
Un saludo.
Enviar un nuevo comentario