La version 4.0 du Framework .NET apporte un bon nombre de nouveautés à la brique de WCF Data Services (ex-Astoria, ex-ADO.NET Data Services), avec notamment le support de la version 2 du protocole OData; vous trouverez sur MSDN une page récapitulative de ces nouveautés.
Une nouveauté qui n’est malheureusement pas souvent mise en avant est la disponibilité dans cette nouvelle version des “Friendly Feeds”, ou “Customizable Feeds”, autrement dit la personnalisation des flux OData générés par Data Services. Cette possibilité est néanmoins bien documentée dans MSDN dans l’article “Feed Customization”, et je vais essayer ici de vous donner un exemple pratique de mise en oeuvre.
L’idée principale de cette fonctionnalité est de vous permettre de personnaliser le flux Atom/AtomPub généré auomatiquement, afin de spécifier par exemple comment les éléments standard Atom doivent être remplis, voire même ajouter des éléments complètement personnalisés afin d’enrichir le flux.
Je vois deux applications principales à cette fonctionnalité:
Pour illustrer le premier point, prenons un flux OData standard représentant, dans notre exemple, des stations Vélib’, incluant leurs coordonnées géographiques. Voici une entrée Atom correspondant à l’une des stations:
<entry> <id>http://localhost:10420/Stations.svc/StationsVelib(16122)</id> <title type="text"></title> <updated>2010-08-12T15:18:43Z</updated> <author> <name /> </author> <link rel="edit" title="StationsVelib" href="StationsVelib(16122)" /> <category term="ODataModel.StationsVelib" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:id m:type="Edm.Int32">16122</d:id> <d:arrd>16</d:arrd> <d:nom_arrd>16ème arrondissement</d:nom_arrd> <d:nom>station_16122</d:nom> <d:description xml:space="preserve">...</d:description> <d:adresse>Route de la muette a neuilly - 75016 paris</d:adresse> <d:lat m:type="Edm.Double">2.2585</d:lat> <d:long m:type="Edm.Double">48.8798</d:long> </m:properties> </content></entry>
</HTML
Ce document XML est parfaitement exploitable, mais que se passe-t-il si on l’affiche dans une application ne comprenant “que” le format Atom standard? Avec (au hasard) Internet Explorer 8, on obtient, pour une liste de stations, quelque chose comme ça:
Pas bien utile! Alors que l’on a dans le flux tout un tas d’informations qu’il serait bien utile d’afficher à ce stade, comme le nom de la station ou sa description. Une fois le flux Atom personnalisé, l’on obtiendra quelque chose comme ça:
Beaucoup plus sympathique, non? De plus, si l’on regarde le XML généré, l’on remarque une autre nouveauté:
<entry> <id>http://localhost:10420/Stations.svc/StationsVelib(16122)</id> <title type="text">station_16122</title> <summary type="html">Route de la muette a neuilly - 75016 paris</summary> <updated>2010-08-12T15:22:39Z</updated> <author> <name /> </author> <link rel="edit" title="StationsVelib" href="StationsVelib(16122)" /> <category term="ODataModel.StationsVelib" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:id m:type="Edm.Int32">16122</d:id> <d:arrd>16</d:arrd> <d:nom_arrd>16ème arrondissement</d:nom_arrd> <d:nom>station_16122</d:nom> <d:description xml:space="preserve">...</d:description> <d:adresse>Route de la muette a neuilly - 75016 paris</d:adresse> <d:lat m:type="Edm.Double">2.2585</d:lat> <d:long m:type="Edm.Double">48.8798</d:long> </m:properties> </content> <geo:lat xmlns:geo="http://www.georss.org/georss">2.2585</geo:lat> <geo:long xmlns:geo="http://www.georss.org/georss">48.8798</geo:long></entry> </HTML
<entry> <id>http://localhost:10420/Stations.svc/StationsVelib(16122)</id> <title type="text">station_16122</title> <summary type="html">Route de la muette a neuilly - 75016 paris</summary> <updated>2010-08-12T15:22:39Z</updated> <author> <name /> </author> <link rel="edit" title="StationsVelib" href="StationsVelib(16122)" /> <category term="ODataModel.StationsVelib" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:id m:type="Edm.Int32">16122</d:id> <d:arrd>16</d:arrd> <d:nom_arrd>16ème arrondissement</d:nom_arrd> <d:nom>station_16122</d:nom> <d:description xml:space="preserve">...</d:description> <d:adresse>Route de la muette a neuilly - 75016 paris</d:adresse> <d:lat m:type="Edm.Double">2.2585</d:lat> <d:long m:type="Edm.Double">48.8798</d:long> </m:properties> </content> <geo:lat xmlns:geo="http://www.georss.org/georss">2.2585</geo:lat> <geo:long xmlns:geo="http://www.georss.org/georss">48.8798</geo:long></entry>
Outre le fait que les éléments Atom standard sont maintenant bien renseignés, l’on voit que les coordonnées géographique de la station sont maintenant exposées sous la forme d’éléments geo:lat et geo:long au sein même de l’élément entry, ce qui rend de fait notre flux conforme GeoRSS, et donc directement exploitable, par exemple, dans Bing Maps:
Alors, comment qu’on fait?
En bref, la méthode est simple et consiste à modifier le fichier EDMX (Entity Data Model) généré par Visual Studio, afin d’ajouter dans la partie CSDL (Conceptual Schema Definition) des attributs supplémentaires qui permettront d’indiquer à WCF Data Services ce qu’il doit faire. Ces attributs supplémentaires ne font pas partie du format CSDL standard, et ne sont donc pas supportés directement par l’outillage Visual Studio; il faut donc aller éditer le fichier EDMX à la main.
Pour ce faire, il suffit d’ouvrir votre fichier EDMX avec l’éditeur XML (clic droit sur le fichier .edmx, “Ouvrir avec…”, choisir l’éditeur XML), de replier la partie edmx:StorageModels qui ne nous intéresse pas, et de nous concentrer sur notre EntityType, où nous allons faire nos modifications.
Voici mon EntityType original:
<EntityType Name="StationsVelib"> <Key> <PropertyRef Name="id" /> </Key> <Property Name="id" Type="Int32" Nullable="false" /> <Property Name="arrd" Type="String" MaxLength="255" Unicode="true" FixedLength="false" /> <Property Name="nom_arrd" Type="String" MaxLength="255" Unicode="true" FixedLength="false" /> <Property Name="nom" Type="String" MaxLength="255" Unicode="true" FixedLength="false" /> <Property Name="description" Type="String" MaxLength="Max" Unicode="true" FixedLength="false" /> <Property Name="adresse" Type="String" MaxLength="255" Unicode="true" FixedLength="false" /> <Property Name="lat" Type="Double" /> <Property Name="long" Type="Double" /></EntityType>
Les extensions proposées par WCF Data Services vont tout simplement prendre la forme d’attributs supplémentaires que l’on va ajouter aux éléments Property qui nous intéressent. Voici les attributs que je vais utiliser:
Encore une fois, ces attributs sont documentés de façon exhaustive dans MSDN.
Pour utiliser les extensions, commençons par référencer le nouveau schéma dans notre fichier EDMX:
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
Puis l’on peut faire nos modifications. Voici mon EntityType modifié:
<EntityType Name="StationsVelib"> <Key> <PropertyRef Name="id" /> </Key> <Property Name="id" Type="Int32" Nullable="false" /> <Property Name="arrd" Type="String" MaxLength="255" Unicode="true" FixedLength="false" /> <Property Name="nom_arrd" Type="String" MaxLength="255" Unicode="true" FixedLength="false" /> <Property Name="nom" Type="String" MaxLength="255" Unicode="true" FixedLength="false" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_EpmKeepInContent="true" /> <Property Name="description" Type="String" MaxLength="Max" Unicode="true" FixedLength="false" /> <Property Name="adresse" Type="String" MaxLength="255" Unicode="true" FixedLength="false" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="html" m:FC_EpmKeepInContent="true" /> <Property Name="lat" Type="Double" m:FC_TargetPath="lat" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix="geo" m:FC_KeepContent="true" /> <Property Name="long" Type="Double" m:FC_TargetPath="long" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix="geo" m:FC_KeepContent="true" /></EntityType>
L’on voit donc que j’ai simplement ajouté des attributs aux propriétés que je souhaitais exposer. Il me suffit de recompiler la solution, et WCF Data Services prendra automatiquement en compte mes indications pour personnaliser le flux Atom généré!
J’espère vous avoir montré comment exploiter les “Friendly Feeds” afin d’enrichir vos flux OData afin de les rendre plus lisibles et plus accessibles, et de faciliter l’exploitation de vos données géolocalisées en exposant facilement des flux au format GeoRSS.