El día de hoy hablaré de como consumir un WCF Service. E intentare resolver todos y cada uno de los errores que suelen ocurrir al momento de desarrollar el ejemplo que propongo.
Aunque pareciera algo trivial este ejemplo, lo cierto es que no todo es como se ve en los webcast, libros y conferencias. A veces surgen errores que no son comunes pero nos quitan mucho tiempo al momento de toparnos con ellos.
El ejemplo que propongo hoy, se trata de una simple calculadora que recibe un número y calcula su cuadrado, es decir X2.
Primero que nada, creamos el proyecto Silverlight que será el cliente del WCF service, junto con la pagina de prueba que utilizaremos para invocar el archivo .xap generado por el proyecto de Silverlight.
Agregamos un poco de código, cabe mencionar que pueden descargar el código de aquí.
Y ahora ejecutamos nuestra página de prueba que invoca el objeto Silverlight que acabamos de crear. Y entonces encontramos el primer problema a resolver:
Para fines de desarrollo este problema es de muy fácil resolución. Basta con que se cambie la propiedad “Copy Local” del ensamblado System.Web.Silverlight a “True”
Ahora Escribimos el código correspondiente al WCF Service
Una vez que el servicio está listo para ser ejecutado, debemos detenernos a revisar algunas implicaciones propias de trabajar con Silverlight.
1. Se debe cambiar el tipo de Binding que utiliza el servicio porque Silverlight no soporta el tipo de binding wsHttpBinding, el tipo de binding por defecto, por lo que debe ser cambiado por basicHttpBinding.
2. Cuando trabajamos con WCF Services y Silverlight, las llamadas siempre son usando el modelo asíncrono.
Una vez que tenemos presente estas importantes consideraciones, agregamos la referencia a nuestro servicio, desde el proyecto Silverlight
Agregamos el código necesario para llamar al servicio en el momento que el usuario quiera calcular el cuadrado de un número x. Compilamos y ejecutamos nuestra aplicación ASP.NET demo.
De nuevo nos encontramos con un error en el momento de realizar la solicitud al servicio.
Soporte para peticiones “Cross Domain”
Este es el momento para hablar acerca de dos archivos que debemos conocer para desarrollar con estas tecnologías.
CrossDomain.xml
Este archivo debe estar en el directorio raíz de donde se hostea nuestra aplicación, en este caso, nuestra aplicación aun no está instalada en ningún servidor web, así que basta con que sea agregado en la carpeta en que se encuentra nuestro servicio
La sintaxis de este archivo, básicamente indica los dominios desde los cuales se pueden realizar peticiones hacia nuestra página, en este caso el WCF Service.
La sintaxis de este archivo, básicamente indica los dominios desde los cuales se pueden realizar peticiones hacia nuestra página, en este caso el WCF Service.
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <allow-http-request-headers-from domain="*" headers="*"/> </cross-domain-policy>
Sin embargo este archivo es viejo, desde los primeros días de Macromedia Flash, tal vez el porqué de que no sea totalmente soportado por Silverlight cuando se quiere hacer uso más a detalle del mismo, puesto que no cubre todos los escenarios. En su lugar Microsoft propone el siguiente archivo, que es de uso mas amplio.
ClientAccessPolicy.xml
Si lo que queremos es un control mas fino de cada uno de los detalles del acceso “Cross Domain” deberíamos usar el archivo ClientAccessPolicy.xml, tiene una estructura semejante al anterior pero con un mayor espectro de escenarios cubiertos.
<?xml version="1.0" encoding="utf-8"?> <access-policy> <cross-domain-access> <policy> <allow-from> <domain uri="*"/> </allow-from> <grant-to> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access> </access-policy>
Por último tenemos el código completo para llamar a nuestro servicio.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Globalization; namespace SilverlightApplicationDemo { public partial class Page : UserControl { public Page() { InitializeComponent(); } private void CallService(double number) { CalculatorProxy.CalculatorClient client = new SilverlightApplicationDemo.CalculatorProxy.CalculatorClient(); client.SquareCompleted += new EventHandler<SilverlightApplicationDemo.CalculatorProxy.SquareCompletedEventArgs>(client_SquareCompleted); client.SquareAsync(number); } void client_SquareCompleted(object sender, SilverlightApplicationDemo.CalculatorProxy.SquareCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show('El servicio devolvio un error'); return; } txtResult.Text = e.Result.ToString(CultureInfo.CurrentUICulture); } private void Button_Click(object sender, RoutedEventArgs e) { double number = 0; if (Double.TryParse(txtNumber.Text, out number) == false) { MessageBox.Show('Esto no es un número'); return; } CallService(number); } } }Espero que este post les sea de utilidad y que les ahorre tiempo en sus futuros desarrollos.
Happy Coding!
1 comentarios:
Gracias...
Me ha sido de gran ayuda.
Publicar un comentario