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).
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:
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