Consumir servicios web ASP.NET y WCF en Silverlight (Parte 4)

Este artículo es la cuarta parte de una mini serie que intenta enseñarte como crear, publicar y ahora consumir servicios web, el primer artículo habla de la base de datos que has estado usando, puedes ver aquí como crear servicios web ASP.NET y aquí como crear servicios WCF.

Creo que la mejor manera de manejar ambos servicios anteriormente creados es en una sola aplicación, para ahorrar la parte del diseño te dejo una imagen guía.

Vista

Pero para ahorrar aún mas, puedes descargar aquí el proyecto de inicio.

Ya con el proyecto inicial, en Visual Studio, da clic derecho sobre tu proyecto y selecciona la opción de “Agregar referencia de servicio”.

ReferenciaServicio

En el cuadro de diálogo, comienza con el servicio web ASP.NET, recuerda la URL, algo así como “http://localhost/ServicioASP/Service1.asmx” y después presiona “Go”, deberás ver algo así.

 

Después de presionar “Ok”, repite la misma operación pero ahora con la liga del servicio WCF.

ServicioWCF

Hasta aquí, como puedes ver, el procedimiento es exactamente el mismo para ambos tipos de servicios, la diferencia comenzará de aquí en adelante, vamos primero a declarar cada uno de los objetos de los servicios.

//servicioASP
ServicioDatosASP.Service1SoapClient servicioASP = new ServicioDatosASP.Service1SoapClient();
 
//servicioWCF
ServicioDatosWCF.Service1Client servicioWCF = new ServicioDatosWCF.Service1Client();

Como puedes ver, la diferencia es grande desde aquí, el protocolo de servicio de ASP.NET es SOAP, cuando en WCF utilizas un cliente sin ese protocolo, en los manejadores de eventos para consultar información, tendrás las diferentes líneas.

Consultar Información

Para el servicio ASP.NET necesitas crear primero una clase, de la siguiente forma.

public class NombreContacto
{
public string Nombre { get; set; }
public string Apellidos { get; set; }
public string Telefono { get; set; }
public string Email { get; set; }
}

Y ya con la clase creada, poder usar un evento clic para poder consultar al servicio web.

private void btnObtenerContactosASP_Click(object sender, System.Windows.RoutedEventArgs e)
{
servicioASP.MostrarTodosLosContactosCompleted += new EventHandler<ServicioDatosASP.MostrarTodosLosContactosCompletedEventArgs>(servicioASP_MostrarTodosLosContactosCompleted);
servicioASP.MostrarTodosLosContactosAsync();
}
 
void servicioASP_MostrarTodosLosContactosCompleted(object sender, ServicioDatosASP.MostrarTodosLosContactosCompletedEventArgs e)
{
if (e.Error == null)
{
List listaContactos = new List();
foreach (string entidad in e.Result)
{
NombreContacto contacto = new NombreContacto();
contacto.Nombre = entidad.Split('|')[1];
contacto.Apellidos = entidad.Split('|')[2];
contacto.Telefono = entidad.Split('|')[3];
contacto.Email = entidad.Split('|')[4];
listaContactos.Add(contacto);
}
 
dgDatosASP.ItemsSource = listaContactos;
}
}

Por el lado de WCF tendrás lo siguiente.

private void btnObtenerContactosWCF_Click(object sender, System.Windows.RoutedEventArgs e)
{
servicioWCF.MostrarTodosLosContactosCompleted += new EventHandler<ServicioDatosWCF.MostrarTodosLosContactosCompletedEventArgs>(servicioWCF_MostrarTodosLosContactosCompleted);
servicioWCF.MostrarTodosLosContactosAsync();
}
 
void servicioWCF_MostrarTodosLosContactosCompleted(object sender, ServicioDatosWCF.MostrarTodosLosContactosCompletedEventArgs e)
{
if (e.Error == null)
{
dgDatosWCF.ItemsSource = e.Result;
}
}

¿Como ves? Una gran diferencia ¿no es así? Bueno, también debes considerar que por el lado de XAML hay una diferencia con los DataGrid que estás usando.

Este es el DataGrid que estamos usando para el servicio web ASP.NET.

 

 

Este es el DataGrid que estamos usando para el servicio WCF.

<sdk:DataGridTextColumn Width="130" Header="Apellidos" Binding="{Binding APELLIDOS}"/>
<sdk:DataGridTextColumn Width="130" Header="Teléfono" Binding="{Binding TELEFONO}"/>
<sdk:DataGridTextColumn Width="130" Header="Correo electrónico" Binding="{Binding EMAIL}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>

Si lo pongo en palabras sencillas, la lista que recibimos del servicio WCF es la misma lista que alimenta al DataGrid, solo que al hacer un enlazado de datos le estarás diciendo a que columna debe ir que información.

Insertar Información

Para hacer esta operación los métodos requeridos son los siguientes, primero vamos con el servicio web ASP.NET.

private void btnIngresarASP_Click(object sender, System.Windows.RoutedEventArgs e)
{
servicioASP.InsertarNuevoContactoCompleted += new EventHandler&lt;ServicioDatosASP.InsertarNuevoContactoCompletedEventArgs&gt;(servicioASP_InsertarNuevoContactoCompleted);
servicioASP.InsertarNuevoContactoAsync(txtNombreNuevoASP.Text, txtApellidosNuevoASP.Text, txtTelefonoNuevoASP.Text, txtCorreoNuevoASP.Text);
}
 
void servicioASP_InsertarNuevoContactoCompleted(object sender, ServicioDatosASP.InsertarNuevoContactoCompletedEventArgs e)
{
if (e.Error == null)
{
txtNombreNuevoASP.Text = string.Empty;
txtApellidosNuevoASP.Text = string.Empty;
txtTelefonoNuevoASP.Text = string.Empty;
txtCorreoNuevoASP.Text = string.Empty;
MessageBox.Show("Tu nuevo contacto ha sido agregado");
}
}

En el caso del servicio WCF, será de la siguiente forma.

private void btnIngresarWCF_Click(object sender, System.Windows.RoutedEventArgs e)
{
servicioWCF.InsertarContactoCompleted += new EventHandler&lt;ServicioDatosWCF.InsertarContactoCompletedEventArgs&gt;(servicioWCF_InsertarContactoCompleted);
ServicioDatosWCF.Contacto nuevoContacto = new ServicioDatosWCF.Contacto();
nuevoContacto.Nombre = txtNombreNuevoWCF.Text;
nuevoContacto.APELLIDOS = txtApellidosNuevoWCF.Text;
nuevoContacto.TELEFONO = txtTelefonoNuevoWCF.Text;
nuevoContacto.EMAIL = txtCorreoNuevoWCF.Text;
servicioWCF.InsertarContactoAsync(nuevoContacto);
}
 
void servicioWCF_InsertarContactoCompleted(object sender, ServicioDatosWCF.InsertarContactoCompletedEventArgs e)
{
if (e.Error == null)
{
txtNombreNuevoWCF.Text = string.Empty;
txtApellidosNuevoWCF.Text = string.Empty;
txtTelefonoNuevoWCF.Text = string.Empty;
txtCorreoNuevoWCF.Text = string.Empty;
MessageBox.Show("Tu nuevo contacto ha sido agregado");
}
}

Actualizar información

Para poder modificar elementos de nuestros contactos lo primero que debes hacer es manejar el manejador para el evento SelectionChanged de los respectivos DataGrid.

En el caso de ASP.NET te debe quedar así.

private void dgDatosASP_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
contactoElegidoASP = new NombreContacto();
contactoElegidoASP = dgDatosASP.SelectedItem as NombreContacto;
txtNombreModificarASP.Text = contactoElegidoASP.Nombre;
txtApellidosModificarASP.Text = contactoElegidoASP.Apellidos;
txtTelefonoModificarASP.Text = contactoElegidoASP.Telefono;
txtCorreoModificarASP.Text = contactoElegidoASP.Email;
}

Y en el caso de WCF será así.

private void dgDatosWCF_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
contactoElegidoWCF = new ServicioDatosWCF.Contacto();
contactoElegidoWCF = dgDatosWCF.SelectedItem as ServicioDatosWCF.Contacto;
txtNombreModificarWCF.Text = contactoElegidoWCF.Nombre;
txtApellidosModificarWCF.Text = contactoElegidoWCF.APELLIDOS;
txtTelefonoWCF.Text = contactoElegidoWCF.TELEFONO;
txtCorreoModificarWCF.Text = contactoElegidoWCF.EMAIL;
}

Y en el caso del evento clic de los respectivos botones, te debe quedar de la siguiente manera.

Para el evento del botón de ASP.

private void btnModificarASP_Click(object sender, System.Windows.RoutedEventArgs e)
{
servicioASP.ActualizarContactoCompleted += servicioASP_ActualizarContactoCompleted;
servicioASP.ActualizarContactoAsync(contactoElegidoASP.ID, txtNombreModificarASP.Text, txtApellidosModificarASP.Text, txtTelefonoModificarASP.Text, txtCorreoModificarASP.Text);
}
 
void servicioASP_ActualizarContactoCompleted(object sender, ServicioDatosASP.ActualizarContactoCompletedEventArgs e)
{
if (e.Error == null)
{
txtNombreModificarASP.Text = string.Empty;
txtApellidosModificarASP.Text = string.Empty;
txtTelefonoModificarASP.Text = string.Empty;
txtCorreoModificarASP.Text = string.Empty;
MessageBox.Show("Tu registro ha sido actualizado");
}
}

Y para el evento del botón WCF.

private void btnModificarWCF_Click(object sender, System.Windows.RoutedEventArgs e)
{
servicioWCF.ActualizarContactoCompleted += new EventHandler&lt;ServicioDatosWCF.ActualizarContactoCompletedEventArgs&gt;(servicioWCF_ActualizarContactoCompleted);
servicioWCF.ActualizarContactoAsync(contactoElegidoWCF);
}
 
void servicioWCF_ActualizarContactoCompleted(object sender, ServicioDatosWCF.ActualizarContactoCompletedEventArgs e)
{
if (e.Error == null)
{
txtNombreModificarWCF.Text = string.Empty;
txtApellidosModificarWCF.Text = string.Empty;
txtTelefonoWCF.Text = string.Empty;
txtCorreoModificarWCF.Text = string.Empty;
MessageBox.Show("Tu registro ha sido actualizado");
}
}

¡Listo! De esta manera podrás comenzar a hacer grandes aplicaciones, hay muchas “best practices” que debes considerar aquí, en este caso los fines son meramente didácticos, ya solo te falta a ti encontrar la opción de borrar elementos para que puedas comenzar con la base mas importante para poder crear aplicaciones empresariales de la manera mas sencilla posible.

Si tienes alguna duda o error con tu aplicación, puedes descargar el código aquí.

Ya lo sabes, si aún así te estás trabando en algo, solo escríbelo en los comentarios, con gusto veremos cuales son los problemas.

13 Comments

  • UnoQuePasaba
    18 febrero, 2012 - 9:49 am | Permalink

    veo que me he perdido ante esto..estoy trabajando con silverlight, WFC, EF y es mucho mas sencillo de lo que aparece… usamos webservices del tipo svc (no asmx), pero imagino que lo explicaras otro dia no??

    • Amin
      18 febrero, 2012 - 3:14 pm | Permalink

      Ya publique una entrada de los servicios WCF, efectivamente hacerlo de esta forma es utilizar Entity Framework, en este artículo utilizé ambas plataformas, tanto ASP.NET como WCF, no se si te confundiste entre servicios o que paso, si tienes alguna duda solo pregunta y vamos resolviendolas una a una ¿qué te parece?

  • 18 junio, 2012 - 7:40 pm | Permalink

    Que tal muy buen tutoria.. lo segui con exito.. si quiero consumir servicios web alojados en un servidor diferente como debe ser la configuración???

    • Amin Espinoza
      18 junio, 2012 - 7:49 pm | Permalink

      Deber poder tener un archivo crossdomain.xml y domainaccesspolicy.xml, de esta forma tu puedes configurar el dominio con el que accederás a tus datos

  • 31 julio, 2012 - 3:13 am | Permalink

    buen post esta muy bien explicado solo quisiera saber como enlazar un combobox con este servicio ya que he buscado y no he encontrado nada gracias espero y me sepas conetestas mi duda

  • 12 noviembre, 2012 - 10:16 pm | Permalink

    Felicitaciones por el Aporte, excelente, pero tengo problemas al utilizas el servicio WCF cuando la consulta tiene como resultado más de 1600 registros.
    ¿Hay que relizar o configurar algo más?

    • Amin Espinoza
      13 noviembre, 2012 - 5:09 pm | Permalink

      No lo creo Antonio, para mi experiencia solo deberás considerar estalecer parámetros de tiempo y rendimiento a partir de los 5000 registros, la media tiende a ser de 500 – 2000 elementos entonces yo podría sugerir que no necesitas mas configuración que la mostrada aquí.

  • 25 febrero, 2013 - 3:08 pm | Permalink

    Hola Amin, muchas gracias por el post, esta buenisimo, sirve muchisimo. Lo unico tengo un problema y no se solucionarlo, cuando agrego la linea de codigo ServiceReference1.Service1Client servicioWCF = new ServiceReference1.Service1Client(); y lo pongo en ejecucion me dice “El codigo de usuario no controlo KeyNotFoundException” y abajo “La clave proporcionada no se encontró en el diccionario.” y no se que es! Si me pudieras ayudar, te agradeceria muchisimo!!!

    Y otra cosa si puede ser, que des algun ejemplo para hacerlo todo en capas, con enterprise library, Muchas gracias!
    Saludos

    • Amin Espinoza
      25 febrero, 2013 - 4:20 pm | Permalink

      Hola pablo, podrías enviarme una captura de pantalla para poder ver cual es el problema? Yo creo que va por la onda de los endpoint pero no quiero confirmar sino tengo una pantalla. Enviala y vemos que onda te parece?

  • 25 febrero, 2013 - 10:48 pm | Permalink

    Hola Amin, antes que nada, gracias por tu respuesta! Ahi te va una imagen del error, http://img687.imageshack.us/img687/3079/errorsilvelight.png
    De paso te cuento como estoy haciendo mi proyecto y me decis si voy bien encaminado, tengo 5 proyectos que son: los 2 primeros son el de silverlight y el web, despues los otros son, una libreria de clases con atributos, otro que es el de web services, y el ultimo una libreria de clase de silvelight en donde agrego las clases como link desde la otra libreria de clases de C#, podre seguir haciendolo asi? O me conviene de otra forma?
    Muchisimas gracias por tu tiempo!
    Saludos!!!

  • 10 mayo, 2015 - 12:52 am | Permalink

    Hola muy buen aporte. Necesito de tu orientación, tengo un Wcf que a través de un solo método (con todos los campos del tipo string) actualiza o inserta un registro con 76 campos de una tabla en sql server y obviamente este Wcf esta escuchando para ser consumido.

    El punto es que ahora, me pidieron modificar el método, debiendose ser una tabla. Como sería ?

    • Amin Espinoza
      11 mayo, 2015 - 3:19 am | Permalink

      Arturo, definitivamente tu única opción es modificar por completo tu servicio WCF, sé que te dará mucho más trabajo pero si lo haces ahora te ahorrarás muchos dolores de cabeza. Si deseas mantener todas las operaciones en un solo método, que te parece si creas 76 métodos internos y a partir de ahí solo invocas desde un método público a toda la información? Eso podría hacer al menos lo minimimamente escalable el servicio.

  • Rodrigo
    20 abril, 2016 - 8:20 pm | Permalink

    tengo un WCF, que es consumido por silverlight, y funciona en ambientes de desarrollo, pero no funciona en ambientes de produccion.

  • Deja un comentario

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    This blog is kept spam free by WP-SpamFree.