Introduction▲
WCF Data Services est un framework permettant d'effectuer des requêtes sur des services de données disponibles sur le web ou en intranet. Les données sont transmises sous la forme de requêtes REST (Representational State Transfer), identifiées par des URL.
Les applications clientes utilisent bien souvent des requêtes HTTP (GET, POST, PUT et DELETE) afin de procéder aux différentes transactions. Les formats utilisés pour représenter et transporter ces données sont en général ceux que l'on retrouve dans des formats d'échange de données tels que JSON, AtomPub et surtout XML.
À travers cet article, nous aborderons les nouveautés qu'apporte la nouvelle version de WCF Data Services 1.5, par rapport à sa précédente mouture.
1. Prérequis▲
Pour travailler avec WCF Data Services 1.5, plusieurs
éléments devront être installés sur votre ordinateur :
-
Microsoft.NET Framework 3.5 SP1 disponible à cette adresse :
http://www.microsoft.com/downloads/details.aspx?displaylang=fr&FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7 -
Visual Studio 2008 SP1 ou Microsoft Visual Web Developer 2008 Express Edition ou une version ultérieure :
http://www.microsoft.com/downloads/details.aspx?FamilyID=fbee1648-7106-44a7-9649-6d9f6d58056e&displaylang=fr -
ou encore
http://www.microsoft.com/downloads/details.aspx?FamilyID=fbee1648-7106-44a7-9649-6d9f6d58056e&displaylang=fr -
La CTP2 d'ADO.NET Data Services v1.5 disponible à cette adresse :
http://www.microsoft.com/downloads/details.aspx?familyid=A71060EB-454E-4475-81A6-E9552B1034FC&displaylang=en
2. Liste des nouveautés de WCF Data Services 1.5▲
2-1. La liaison de données sous WPF et Silverlight 2▲
Première nouveauté : celle-ci concerne la liaison des données sous Windows Presentation Foundation et Silverlight 2. Désormais, il est possible de mettre à jour automatiquement les données de la source vers la cible, mais également dans le sens inverse.
2-1-1. Création du service Web▲
Nous allons, par l'intermédiaire d'un exemple, créer un
service de données Web et un client WPF qui nous
permettra d'illustrer cette nouveauté.
On crée un nouveau site Web (Fichier > Nouveau > Projet) :
On choisit une application de service Web ASP.NET. Nous ajoutons ensuite un nouvel objet de type Service de données ADO.NET :
Nous pouvons à présent créer le modèle de données de notre service Web en ajoutant un objet de type ADO.NET Entity Data Model :
En cliquant sur [Ajouter], un assistant apparaît, proposant de générer un modèle à partir d'une base de données ou de créer un modèle vide. Pour cet exemple, j'ai opté pour la première solution en suivant les étapes proposées et en sélectionnant la table [Membre] de ma base de données.
Cette table contient les enregistrements suivants :
Une fois en possession de tous ces éléments, nous pouvons commencer à écrire notre application. Dans un premier temps, nous allons nous attaquer au code du service Web.
Voici notre fichier [WebDataServiceDeveloppez.svc.cs], tel qu'il est à sa création :
namespace
WebServiceDeveloppez
{
public
class
WebDataServiceDeveloppez :
DataService<
/*TODO : placez ici le nom de votre
* classe source de données */
>
{
// Cette méthode n'est appelée qu'une seule fois
// pour initialiser les srtatégies au niveau des services.
public
static
void
InitializeService
(
IDataServiceConfiguration config)
{
//config.SetEntitySetAccessRule("*", EntitySetRights.All);
//config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
}
}
Il s'agit d'une classe qui dérive d'un service de données.
La première balise de commentaires nous indique qu'il nous faut
sélectionner la classe qui sera utilisée en tant que source de données.
Ayant précédemment utilisé un modèle de données de type [ADO.NET Entity],
la classe à utiliser sera [developpezEntities] :
public
class
WebDataServiceDeveloppez :
DataService<
developpezEntities>
On peut lancer l'application pour constater que notre service est bien fonctionnel :
Nous allons maintenant nous intéresser à la suite du code de notre service. Celui-ci contient une méthode [InitializeService] qui permet de configurer les données qui seront visibles via le service :
// Cette méthode n'est appelée qu'une seule fois
// pour initialiser les srtatégies au niveau des services.
public
static
void
InitializeService
(
IDataServiceConfiguration config)
{
//config.SetEntitySetAccessRule("*", EntitySetRights.All);
//config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
La méthode [SetEntitySetAccessRule] permet de configurer les droits d'accès à l'entité spécifiée tandis que la deuxième méthode [SetServiceOperationAccessRule] permet de configurer l'accessibilité aux services. Une fois ces méthodes configurées, on pourra voir apparaître les données :
config.
SetEntitySetAccessRule
(
"*"
,
EntitySetRights.
All);
config.
SetServiceOperationAccessRule
(
"*"
,
ServiceOperationRights.
All);
2-1-2. Création du client WPF▲
Nous allons maintenant créer un client WPF afin de consommer le service de données.
Pour cela, on ajoute un projet de type WPF (Fichier > Ajouter > Nouveau projet) :
À ce projet, nous ajoutons un objet de type [ListView] que nous lierons à la table [Membre] :
<
ListView ItemsSource=
"{Binding Membres}"
Grid.
Row=
"0"
IsSynchronizedWithCurrentItem=
"True"
Name=
"listView"
>
<
ListView.
View>
<
GridView>
<
GridView.
Columns>
<
GridViewColumn Header=
"Nom"
>
<
GridViewColumn.
CellTemplate>
<
DataTemplate>
<
TextBox Width=
"100"
Text=
"{Binding Nom}"
/>
</
DataTemplate>
</
GridViewColumn.
CellTemplate>
</
GridViewColumn>
<
GridViewColumn Header=
"Prénom"
>
<
GridViewColumn.
CellTemplate>
<
DataTemplate>
<
TextBox Width=
"100"
Text=
"{Binding Prenom}"
/>
</
DataTemplate>
</
GridViewColumn.
CellTemplate>
</
GridViewColumn>
<
GridViewColumn Header=
"Rôle"
>
<
GridViewColumn.
CellTemplate>
<
DataTemplate>
<
TextBox Width=
"120"
Text=
"{Binding Role}"
/>
</
DataTemplate>
</
GridViewColumn.
CellTemplate>
</
GridViewColumn>
</
GridView.
Columns>
</
GridView>
</
ListView.
View>
</
ListView>
Le [ListView] contient 3 colonnes (Nom, Prénom et Rôle) avec des champs éditables. Nous ajouterons également des [TextBox] (1 pour chaque information) qui feront office de "cibles" ainsi qu'un [Button] pour valider nos changements :
<
TextBox Grid.
Row=
"0"
Grid.
Column=
"2"
Text=
"{Binding Nom}"
Name=
"TextBox1"
/>
<
TextBox Grid.
Row=
"1"
Grid.
Column=
"2"
Text=
"{Binding Prenom}"
Name=
"TextBox2"
/>
<
TextBox Grid.
Row=
"2"
Grid.
Column=
"2"
Text=
"{Binding Role}"
Name=
"TextBox3"
/>
<
Button Grid.
Row=
"3"
Grid.
Column=
"2"
HorizontalAlignment=
"Right"
Content=
"Valider"
Click=
"Button_Click"
/>
On définira le code behind de la façon suivante :
public
partial
class
Window1 :
Window
{
WebDataServiceDeveloppez.
developpezEntities wds;
private
HashSet<
object
>
_modifiedEntities =
new
HashSet<
object
>(
);
public
ObservableCollection<
Membre>
Membres {
get
;
private
set
;
}
public
Window1
(
)
{
InitializeComponent
(
);
wds =
new
WebDataServiceDeveloppez.
developpezEntities
(
new
Uri
(
"http://localhost:1083/WebDataServiceDeveloppez.svc"
));
this
.
Membres =
new
ObservableCollection<
Membre>(
wds.
Membre);
this
.
DataContext =
this
;
}
private
void
Button_Click
(
object
sender,
RoutedEventArgs e)
{
foreach
(
var
membre in
_modifiedEntities)
{
wds.
UpdateObject
(
membre);
}
wds.
SaveChanges
(
);
_modifiedEntities.
Clear
(
);
}
}
Nous faisons appel à notre source de données, puis nous initialisons une collection d'objets de type [Membre] avec les informations fournies par la source. Dans l'événement [Click] du [Button], on met à jour la source de données.
Si l'on compile le projet, on obtient la fenêtre suivante :
Si l'on modifie une information sur la source (ou la cible), la mise à jour est également faite sur la cible (ou la source).
2-2. Comptage des entités▲
Il est désormais possible de déterminer le nombre d'entités
d'une table selon les filtres que l'on désire appliquer.
Il suffit d'ajouter l'attribut $count dans l'URI, la table
sur laquelle on va filtrer ainsi que le filtre.
Par exemple, le lien URI suivant renverra 3 :
http://localhost:1083/WebDataServiceDeveloppez.svc/Membre/$count?$top=3
D'autres exemples de requêtes :
Requête | Réponse |
---|---|
/Membre/$count | 3 |
/Membre/$count?$top=100 | 3 |
/Membre/$count?$top=2 | 2 |
2-3. Mappage personnalisé▲
Par défaut, WCF Data Services utilise le protocole AtomPub
pour exposer les données sur le Web.
Dans la nouvelle version d'WCF Data Services 1.5, il existe une fonctionnalité que
l'on appelle le mappage personnalisé. Celle-ci nous permet
de mapper une propriété à un élément sans passer par AtomPub.
Ceci est aussi bien valable pour un élément prédéfini (ex. :
[Nom] ou [Prenom] dans la table [Membre]) que pour un élément
personnalisé. De ce fait, on dispose d'informations supplémentaires
dans notre service de données qui peuvent être interprétées par
des clients à même de les comprendre.
2-4. Pagination contrôlée du côté serveur▲
Lorsqu'un utilisateur soumet une requête qui risque de renvoyer une multitude de données du serveur, le service Web peut forcer une mise en page et ne retourner que les enregistrements désirés au client. Si la pagination est exécutée, un lien URI sera inclus dans la requête, permettant de diriger le client vers la prochaine page.
2-5. Meilleure prise en charge du BLOB (Binary Large OBject)▲
Si une entité contient des données binaires, on peut les séparer en deux parties : les liens et les ressources. Les ressources représentent les données binaires actuelles tandis que les liens représentent les métadonnées et les informations supplémentaires des données binaires. On peut également effectuer des requêtes sur l'un ou l'autre.
2-6. Projection (requête SELECT)▲
On peut effectuer une requête SELECT en ajoutant $select à notre URI.
Ce nouvel attribut nous permet de spécifier les données de la table
que l'on souhaite retourner. Par exemple, l'URI suivant ne renverra
que le champ [Role] de la table [Membre] :
http://localhost:1083/WebDataServiceDeveloppez.svc/Membre?$select=Role
Pour retourner plusieurs champs, on utilise la virgule comme séparateur :
http://localhost:1083/WebDataServiceDeveloppez.svc/Membre?$select=Nom,Role
3. Conclusion▲
Au cours de cet article, nous avons passé en revue
les nouvelles fonctionnalités associées à WCF Data Services 1.5.
Ce produit en est à sa première évolution, mais celles-ci apportent
un peu plus de conforts aux développeurs.
J'aimerais simplement remercier les membres de l'équipe Dotnet de Développez qui m'ont aidé tout au long de la rédaction de cet article, plus particulièrement Thomas Levesque pour ses conseils et son expérience sur WPF, ainsi que Louis-Guillaume Morand, Melem et Wachter pour les corrections apportées à cet article.