Capitulo 7 : WCF Data Services (Parte 2)

Lección 2: Consumiendo WCF Data Services

Agregando una aplicación cliente nos permite consumir y mostrar los datos según sea necesario.

Agregando una aplicación cliente
Anteriormente se creo una solución de ejemplo llamada WcfDataServicesSolution con una aplicación web WcfDataServicesLibrary. Para agregar una aplicación cliente, WPFWpfClient: clic en el Explorador de soluciones, Agregar | Nuevo proyecto | Windows y seleccione la plantilla Aplicación WPF.

Cuando la aplicación cliente está creada, en el archivo MainWindows.xaml se debe agregar una fila al control Grid para un menú y una segunda fila para un DataGrid. Añadir el menú y el DataGrid (dg) y establecer la propiedad AutoGenerateColumns en true. En el menú, agregar un MenuItem para recuperar la colección Clientes y mostrarlos en el DataGrid.

Para recuperar la colección de los clientes en el MenuItem, en la ventana Propiedades, clic en el evento Click, escribir GetCustomers, y Enter. (Esto crea el método GetCustomers en el código).

Ejemplo del XAML generado:

<Grid>

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<Menu>

<MenuItem Header="Leccion 2">

<MenuItem Header="Obtener Clientes" Click="getCustomers" />

<MenuItem Header="Save"/>

</MenuItem>

</Menu>

<DataGrid AutoGenerateColumns="True" Grid.Row="1" Name="dg" />

</Grid>

Referenciando un WCF Data Service
Para agregar una referencia de servicio, en la aplicación WpfClient, clic en el proyecto, Add service reference. Cuando aparezca la ventana de servicio, clic en Discover, para mirar a través de la solución web y los servicios WCF. Seleccionar NorthwindService y copiar la dirección (la necesitamos mas tarde).

clip_image001

Haga clic en Aceptar para agregar la referencia. Esto crea las clases proxy de la aplicación que aparecen y que sirven para comunicarse con el servicio de WCF de datos (Reference.datasvcmap/Reference.cs.file).

Las clases de proxy, heredan de NorthwindEntities DataServiceContext (DataServiceContext se comporta como ObjectContext pero en el cliente, usando URIs).

 

Estableciendo enlaces al Servicio de datos de WCF con DataServiceCollection

Al enlazar los datos a un DataGrid de WPF o Silverlight , normalmente se asignan a la propiedad ItemsSource. Si se quiere modificar los datos de la cuadrícula de datos y guardar los cambios, cuando se ejecuta el método SaveChanges en el objeto DataServiceContext, nada se salva porque no sabe que cambios se quieren guardar, primero se deben notificar al DataServiceContext.

Para enlazar la colección de clientes al DataGrid, clic en el menú, agregue código para crear instancias de la clase NorthwindEntities y asignar el objeto en el campo db. A continuación, en el método GetCustomers, agregar el código para crear un objeto DataServiceCollection y pasar db.Customers en el constructor. Agregar el código para asignar el datasource al DataGrid (dg):

El código quedaría:

-------------------------------------VB-------------------------------------------

Imports System.Data.Services.Client

Imports WpfClient.NorthwindServiceReference

Class MainWindow

Dim db As New NorthwindEntities( _

New Uri("http://localhost:65363/NorthwindService.svc"))

Private Sub getCustomers(ByVal sender As System.Object, _

ByVal e As System.Windows.RoutedEventArgs)

Dim source = New DataServiceCollection(Of Customer)(db.Customers)

dg.ItemsSource = source

End Sub

End Class

-------------------------------------CS-------------------------------------------

using System;

using System.Data.Services.Client;

using System.Windows;

using WpfClient.NorthwindServiceReference;

namespace WpfClient

{

public partial class MainWindow : Window

{

private NorthwindEntities db = new NorthwindEntities(

new Uri("http://localhost:57087/NorthwindService.svc"));

public MainWindow()

{

InitializeComponent();

}

private void getCustomers(object sender, RoutedEventArgs e)

{

var source = new DataServiceCollection<Customer>(db.Customers);

dg.ItemsSource = source;

}

}

}

Antes de ejecutar la aplicación, se debe establecer como proyecto de inicio a la aplicación WCFClient y la pantalla nos mostraría:

clip_image002

Para poder guardar los cambios en la base de datos,se puede ejecutar el método SaveChanges que permite pasar un valor de enumeración SaveChangesOption:

Nombre

Descripción

None

Los cambios pendientes se guardan mediante varias solicitudes al servidor, pero la operación se detiene cuando se produce el primer error (valor predeterminado).

Batch

Todos los cambios pendientes se guardan en una sola solicitud por lotes.

ContinueOnError

Los cambios pendientes se guardan mediante varias solicitudes al servidor y la operación continúa después de que se produce un error.

ReplaceOnUpdate

Las actualizaciones pendientes se realizan reemplazando todos los valores de la entidad en el origen de datos con valores de la entidad actualizada (HTTP PUT) en lugar de actualizando valores cambiados (HTTP MERGE), que son el comportamiento predeterminado.

En el XAML del MenuItem en Guardar: ir a la ventana Propiedades, clic en el evento Click, escribir SaveToDataBase. En este método, se llama al método SaveChanges y se muestra un mensaje:

-------------------------------------VB-------------------------------------------

Private Sub saveToDatabase(ByVal sender As System.Object, _

ByVal e As System.Windows.RoutedEventArgs)

db.SaveChanges()

MessageBox.Show("Salvado")

End Sub

-------------------------------------CS-------------------------------------------

private void saveToDatabase(object sender, RoutedEventArgs e)

{

db.SaveChanges();

MessageBox.Show("Salvado");

}

Especificando un formato de carga útil (Payload)
Para la transmisión de mensajes entre el cliente y el servicio de WCF de datos, los formatos soportados son AtomPub y JSON. AtomPub es un formato XML  y JSON es  JavaScript Object Notation.

En lugar de comenzar y terminar las etiquetas, JSON utiliza llaves {}. El objeto DataServiceContext solo soporta el formato AtomPub, pero si se utiliza la clase WebClient para enviar las solicitudes, se puede especificar un encabezado de Accept=application/json.

Tipo Mime Requerido

Tipo Mime de respuesta

Formato de Serialización

*/*

application/atom+xml

AtomPub

text/*

Not supported

N/A

application/*

Not supported

N/A

text/xml

text/xml

AtomPub

application/xml

application/xml

AtomPub

application/atom+xml

application/atom+xml

AtomPub

application/json

application/json

JSON

Ejemplo de otro elemento de menú para recuperara un cliente utilizando el formato AtomPub y el formato JSON, utilizando la clase System.Net.WebClient para llamar a un servicio WCF.

-------------------------------------VB-------------------------------------------

Private Sub getCustomerWebClient(ByVal sender As System.Object, _

ByVal e As System.Windows.RoutedEventArgs)

Dim uri = db.BaseUri.ToString() + "/Customers('ALFKI')"

Using client = New WebClient()

Dim result = client.DownloadString(uri)

MessageBox.Show(result)

End Using

Using client = New WebClient()

client.Headers("Accept") = "application/json"

Dim result = client.DownloadString(uri)

MessageBox.Show(result)

End Using

End Sub

-------------------------------------CS-------------------------------------------

private void getCustomerWebClient(object sender, RoutedEventArgs e)

{

var uri = db.BaseUri.ToString() + "/Customers('ALFKI')";

using (WebClient client = new WebClient())

{

var result = client.DownloadString(uri);

MessageBox.Show(result);

}

using (WebClient client = new WebClient())

{

client.Headers["Accept"] = "application/json";

var result = client.DownloadString(uri);

MessageBox.Show(result);

}

}

Usando interceptores
Se puede conectar con WCF Data Services mediante el uso de interceptores para acceder a los mensajes de solicitud de modo y agregar lógica personalizada a cada operación. Para interceptar un mensaje, se debe  añadir QueryInterceptorAttribute o ChangeInterceptorAttribute sobre los métodos que deseen en el servicio de datos. El atributo interceptor requiere un parámetro string que especifica el conjunto de entidades a las que el interceptor se aplica.

-------------------------------------VB-------------------------------------------

<QueryInterceptor("Customers")> _

Public Function OnQueryCustomers() _

As Expression(Of Func(Of Customer, Boolean))

Return Function(c) c.Country = "USA"

End Function

-------------------------------------CS-------------------------------------------

[QueryInterceptor("Customers")]

public Expression<Func<Customer, bool>> OnQueryCustomers()

{

return c => c.Country=="USA";

}

El ChangeInterceptorAttribute puede interceptar los cambios y la validación o la comprobación de restricciones antes de que las modificaciones se lleven a cabo.Se puede abortar la modificación lanzando una DataServiceException desde el código.

-------------------------------------VB-------------------------------------------

<ChangeInterceptor("Products")> _

Public Sub OnChangeProducts(ByVal product As Product, _

ByVal operations As UpdateOperations)

If operations = UpdateOperations.Add OrElse _

operations = UpdateOperations.Change Then

' Reject changes to discontinued products.

If product.Discontinued Then

Throw New DataServiceException(400, _

String.Format( _

"Modifications not allowed on discontinued product ID:{0} Name:{1}", _

product.ProductID, product.ProductName))

End If

ElseIf operations = UpdateOperations.Delete Then

' Block the delete and instead set the Discontinued flag.

Throw New DataServiceException(400, _

String.Format( _

"Deletion not allowed on discontinued product " + _

"ID:{0} Name:{1} set Discontinued to true", _

product.ProductID, product.ProductName))

End If

End Sub

-------------------------------------CS-------------------------------------------

[ChangeInterceptor("Products")]

public void OnChangeProducts(Product product, UpdateOperations operations)

{

if (operations == UpdateOperations.Add ||

operations == UpdateOperations.Change)

{

// Rechaza cambios a los productos discontinuados.

if (product.Discontinued)

{

throw new DataServiceException(400,

string.Format(

"Modifications not allowed on discontinued product " +

"ID:{0} Name:{1}",

product.ProductID, product.ProductName));

}

}

else if (operations == UpdateOperations.Delete)

{

// Bloquea el borrado y setea la bandera Discontinued.

throw new DataServiceException(400,

string.Format(

"Deletion not allowed on discontinued product " +

"ID:{0} Name:{1} set Discontinued to true",

product.ProductID, product.ProductName));

}

}

Resumen de la lección

·         WCF Data Services proporciona conectividad de datos a cualquier aplicación que tenga acceso a la red de datos (Silverlight, WPF y Windows Forms).

·         Se puede acceder a un servicio de WCF de datos mediante la adición de una referencia de servicio al proyecto.

·         Se usa DataServiceCollection para llevar a cabo una doble vía de unión con los controles DataGrid.

·         Con WCF Data Services, se puede especificar el formato de carga útil (JSON o AtomPub).

·         Los Interceptores pueden interceptar una solicitud de consulta antes de que una operación de servicio sea ejecutada.

 

No hay comentarios:

Publicar un comentario