Cours de C# pour l'ESSI - Cours 04 : XML & Web Services

RACINE
 
Voir dans une fenêtre à part Cliquez ici pour voir la page dans un explorateur séparé.

Index Rapide



Partie 1 : Introduction

Qu'est ce que les Web Services ? Une idée du futur, mais pas forcément récente. Je n'accorderai leur paternité à personne de peur de foudres de tout bord. ;)

Réutilisation

L'idée est simple : l'informatique est modulaire. Nous, développeurs en génie logiciel, ne faisons rien d'autres que des Legos (tm) à longueur de journée (désolé pour les bien pensants, c'est mon avis). Bien peu sont ceux qui créent ; nous réutilisons aussi souvent que possible.
Grand bien nous en prends dans ce métier où on passe notre temps à éviter les bugs, où on tente de gagner du temps de développement, de la stabilité des logiciels.
Autre idée : on n'a pas besoin de tout, tout le temps. Mais par contre quand on veut quelque chose, on l'aimerai bien tout de suite si possible. Et à tant que faire, si les données étaient à jour ce ne serait pas plus mal.

Mise à jour et distribution

La modularité, on l'avait déjà avec les DLL et autres contrôles OCX et VBX. Vous achetiez un composant capable d'une certaine tâche, vous développiez avec et vendiez votre soft avec la version redistribuable du composant. Mais en cas de mise à jour de ce contrôle ou de patch de celui-ci, c'était souvent la Bérézina ! Il fallait demander à tout les utilisateurs de faire une mise à jour ce qui n'est pas forcément simple et implique des coûts pour tout le monde.

Interopérabilité

Un autre point d'importance pas forcément évident si l'on n'y prend garre : l'interopérabilité, notamment dans l'entreprise.
Il y a des firmes spécialisées qui développent des "ponts" entre les différents logiciels utilisés dans l'entreprise. En effet, cette dernière a différents postes qui doivent communiquer entre eux mais qui n'y arrivent que très rarement. Quand à l'idée d'utiliser une suite logicielle, il n'en existe aucune qui convienne à tout les besoins de tout les postes. Alors on trouve des moyens détournés pour faire se marier des logiciels tournant sous différents OS, sur des sites différents, avec des versions différentes des mêmes logiciels. Là où devrait être le travail du développeur, se trouve bien souvent l'utilisateur qui doit effectuer des manipulations pas forcément simples ni constructives pour faire coopérer différents acteurs de la chaine de la valeur.
C'est là où les WebServices se posent en "sauveurs" : ils sont universels (OS et Langage), utilsent un langage libre, normalisé et universel (XML). Ils sont normalisé par un institut indépendant (le W3C, rien que ça) de Microsoft dans le protocol SOAP. De grands noms tels Microsoft, IBM et DevelopMentor sont associés à leur développement.

Un point de vue de Microsoft

Vous trouverez un point de vue de Microsoft sur les WebServices, présenté pour ESSI# par M. Laurent ELLERBACH, responsable relation avec l'enseignement supérieur de Microsoft France.

Ce texte est une EXCELLENTE entrée en matière pour comprendre les WebServices et leur fonctionnement. Complet, il vous permettra d'acquérir les idées clés et les termes courant du monde des services Web. Prenez 5 minutes pour le lire, et plongez vous dans ce cours XML/WebServices pour voir plus en détail "comment marchent les WebServices ...".


Il est plus que conseillé de se référer à la présentation C# vs. Java ainsi qu'à l'initiation en cas difficulté. Les WebServices et l'esprit général d'ASP.NET étant semblables (le premier faisant partie du second) il est souhaitable d'avoir bien compris le cours précédent sur ASP.NET.

ESSI# propose dèsormais des TPs de l'ESSI revisités. Le TP de réseau numéro 1 "RMI vs. WebServices" est très interresant si vous cherchez comment faire des WebServices avec .NET simplement.

Si vous constatez des erreurs, des imprécisions ou que vous avez des problèmes avec ce TP, adressez vous à l'auteur .

Tout le matériel qui est présenté n'est nullement un cours officiel de l'ESSI ou de Microsoft. Il a été produit par l'auteur et en est l'exclusive propriété.
Toutes remarques pouvant aider à l'améliorer ou à corriger les diverses erreurs pouvant subsister sont les bienvenues. (email auteur )

retour à l'index

Partie 2 : XML

Généralités

Le fond

XML est un langage normalisé par un organisme indépendant (le sacro-saint W3C), acronyme de eXtensible Markup Language, c'est un méta-langage (il permet d'en définir d'autres, comme par exemple HTML : HyperText Markup Language). Vous trouverez sa spécification sur le site du W3C.

Dire que XML est intégré à .NET n'est pas un vain mot ! Un namespace complet lui est dédié (System.XML) et on retrouve le XML un peu partout ailleur. (les DataSet peuvent s'exporter en XML/XSLT, ils peuvent aussi en lire, on peut sérialiser des objets ou des classes en XML, ... etc)

Un document XML est UN ARBRE et par conséquent, est toujours composé d'un seul élément ! Bien évidement, c'est l'élément racine qui est généralement une collection de sous éléments.

Les entorses à la règle ci-dessus :
  • les commentaire : <!-- ... des commentaires ... --> qui peuvent être placés partout (attention, ils doivent finir par 2 tirets et non 3)
  • les informations de fichier : <?xml ... encodage, attributs, ... ?> qui sont placés en en-tête
  • les directives DTD (cf chapitre Validation) : <!ELEMENT ... >, <!DOCTYPE ... >, <!ATTLIST ... >, ... Ceci sort de la simple présentation d'XML de ce cours. Retenez que c'est un moyen de spécifier la structure du fichier.

Les informations dans un fichier XML peuvent être :
  • La structure même du fichier (pour décrire un état sans avoir besoin de valeurs)
  • Représentées comme contenues dans des éléments (choisi dans l'exemple DVDTheque)
  • Représentées comme attributs des éléments (<DVD Nom="Le garde du corps" NomOriginal="Yojimbo" ... />)
Le représentation mémoire d'un arbre XML est appelée DOM (Document Object Model) et est ... un arbre. Il permet d'éditer (ajout, suppression, greffes et autres opérations) dans l'arbre en mémoire, ce qui est relativement mieux que dans le fichier XML stocké dans un flux. Bien évidement, c'est "aplati" et "textualisé" qu'est stocké le document dans un fichier XML, mais cette représentation n'est pas performante pour une autre utilisation que le stockage ou la transmission.
Pour plus d'information sur DOM, XML Document Object Model (DOM) (TRÈS UTILE) ou Mapping the Object Hierarchy to XML Data.

La forme

A quoi ça ressemble ? La meilleure réponse c'est à du HTML (en vérité, c'est l'inverse :). Le XML fonctionne avec des balises QUE L'ON FERME TOUJOURS ET QUE L'ON IMBRIQUE CORRECTEMENT !! Pour les balises que l'on ne "ferme pas", celles qui ne fonctionnent pas par couple de balise (comme les images en HTML), on doit préciser un slash (/) en fin de chevron. (ex, <img src="toto.png" />)
Et il est aussi (dans sa normalisation et dans ses implémentations) sensible à la casse. Fini donc les
<HtmL><Body><U><i><B>Bonjour</u></I></BODY></html>
Le HTML est comme XML sensé être bien formé, respecter les casses, etc ... mais aux vues de certaines difficultés découlant de l'internet et du fait que monsieur tout le monde fait du HTML, les implémentations de HTML (browser web) sont obligées de supporter du presque-HTML : l'important étant d'avoir un rendu, même approximatif.
Mais pas en XML !! Le XML manipule des donnée et se doit d'être strict, bien formaté, et car il est universel : bien formalisé.

Voici donc ce que l'on aurait pu trouver :
<HTML><body><U><i><B>Bonjour</B></i></U></body></HTML>

Ci-dessous, vous avez un document XML en entier. C'est la (toute petite) carte d'un (tout petit) restaurant : chaque plat est un élément, il a des attributs qui décrivent son type et si c'est un plat végétarien. De plus, si l'élément contient du texte, c'est un complément au nom du plat (en clair, on peut manger une "Pizza Royale", une "Salade Chèvre chaud" ou une "Quiche").

La carte de la Tour d'Argent


C'est pas compliqué le XML ? Et on sent déjà venir plein de choses sympa : c'est textuel, parsable à souhait et formalisé. Par conséquent, pas de problème de qui l'envoie ou le lit : il sera capable de comprendre qu'il soit manchot, fenêtre ou diablotin . On pourra facilement le faire passer par un filtre pour l'HTMLiser, le PDFiser, stocker des données, etc ...

retour à l'index

Un peu plus loin avec XML

XSLT

Acronyme de eXtensible Stylesheet Language Transformation, c'est un langage qui permet d'expliquer comment transformer du XML en quelque-chose d'autre : on décrit dans ce "langage XML formalisé" comment traiter un fichier XML et produire une sortie (HTML, XML ou texte). Par exemple, transformer du XML en HTML : le XML contient des données, et avec la classe .NET XslTransform vous transformez ces données (suivant le format XSLT voulu) en HTML; vous avez complètement ainsi séparé design et données.

Un EXCELLENT exemple de comment faire cela (XML -> HTML) est disponible chez A List Apart : il est simple, drôle ET pratique. C'est la devise à laquelle j'essaye de me tenir pour mes documents, donc je ne peux que le conseiller.
Vous trouverez aussi, toujours chez A List Apart, un exemple d'utilisation d'XSLT. Il est moins "pratique" que celui référencé ci-dessus, mais apporte une vision plus large sur XSLT. Regardez le, il est complémentaire de celui proposé ci-dessus.

Bien évidement, quelques pages concernant XSLT dans la documentation .NET : Utilité de la classe XslTransform et la classe XslTransform.

Un site de référence sur XSLT : XSLT.com.

retour à l'index

X-Path

Cliquez pour télécharger Cliquez ici pour obtenir les sources du logiciel de requêtes X-Path.
Cliquez pour télécharger Cliquez ici pour obtenir l'exécutable

XML Path (abrégé X-Path) c'est le SQL du XML (bonjour les abréviations !). Tout comme le Simple Query Language, X-Path permet de décrire de manière simple, textuelle, humainement réalisable des requètes sur un fichier XML. Certes, ce n'est pas aussi clair que du SQL (langage de 4ème génération, très éloigné de la machine) et cela ressemble un peu au pseudo-langages utilisés pour les expressions régulières.

Prennons le fichier de notre restaurant (cf plus haut ...). Voici la définition XSD des plats qui composent notre carte (générée avec VS.NET, et visualisée avec).
Schéma XML d'un plat

Schéma XML d'un Plat


Voici comment on récupère une liste de noeuds d'un document XML; ici, nous faisons une requète pour récupérer tout les plats végétariens :

nodeList = doc.DocumentElement.SelectNodes("child::Plat[@vegetarien='oui']");

Grâce à la méthode SelectNodes (SelectNodes dans .NET Doc), on effectue la requête suivante :
  • child : on prend les enfants du noeud courant (la racine)
  • ::Plat : on garde ceux de type Plat
  • [@vegetarien='oui'] : on ne garde que ceux ayant l'attribut vegetarien valant oui (attention aux guillements)
Voilà. C'est pas sorcier X-Path ? Certes, je n'ai fait qu'une requête simplisime mais libre à vous de consulter la définition de X-Path qui contient bien plus de mot clés !! Et pour vous entrainer, vous pouvez utiliser mon petit logiciel qui effectue des requètes sur le fichier XML de notre restaurant. Bien évidement, jetez un oeil aux sources pour voir comment ça marche et adaptez le à vos besoins !

Schéma XML d'un plat

Schéma XML d'un Plat


Des pointeurs utiles :

retour à l'index

XSD

Cliquez pour télécharger Cliquez ici pour obtenir les quelques fichiers pour les test de XSD.EXE.
Cliquez pour télécharger
Cliquez ici pour obtenir le fichier personpet.xsd (tiré de .NET Framework SDK).

XSD est l'acronyme de XML Schema Description. C'est un document XML (of course ;) qui décrit, de manière formalisée par le World Wide Web Consortium (W3C) depuis le 16 mars 2001, de quelle manière en XML un objet ou une relation doit être formé : cela permet de décrire un schéma relationnel. Vous trouverez la spécification du format XSD à l'adresse http://www.w3.org/2001/XMLSchema.

L'outil du framework nommé xsd.exe permet de générer un schéma XSD à partir de classes .NET, et (réciproquement) des définitions de classe (une classe C# ou VB.NET) à partir d'un fichier XSD.
La classe XmlSerializer (Doc .NET) quand elle serialize un objet génère un fichier XML qui est conforme à la description XSD qui aurait été générée par l'outil xsd.exe.

Dans l'exemple à télécharger, on part d'une classe .NET contenant des attributs et méthodes privées et publiques. On génère une assembly les contenant (ici DLL), et un fichier XSD à partir de cet assembly. Puis, on régénère une classe C# à partir de ce fichier XSD. Au final, on obtient l'équivalent de la classe de départ mais ne contenant QUE les attributs publiques.

La classe de départ dans son intégralité

La classe d'arrivée dans son intégralité


Un exemple très interressant de ce que l'on peut faire avec XSD dans .NET est fournis dans les exemples du framework. Si vous avez installé les QuickStart, vous le trouverez à l'URL /howto/samples/xml/savedatasetmapxsdschema/cs/savedatasetmapxsdschema.aspx (sinon sur votre disque dur, généralement sous C:\Program Files\Microsoft.NET\FrameworkSDK\Samples\QuickStart\howto\samples\xml\savedatasetmapxsdschema\cs\savedatasetmapxsdschema.aspx).
Dans cet exemple, on crée un DataSet contenant 2 tables (des hommes et des animaux) et un relation entre ces 2 tables. Et on sauvegarde le schéma de ce DataSet en XSD avec la méthode WriteXmlSchema() (WriteXmlSchema() .NET Doc) du DataSet. Si l'on visualise le fichier .xsd créé avec VisualStudio, on obtient un schéma relationnel de base de donnée des plus sympathiques !

Visualisation *visuelle* d'un fichier XSD

La représentation graphique d'un schéma relationnel XSD


Bien entendu, il n'y a pas là derrière le diabolique Microsofttm de caché, avec un outrageux format propriétaire. Non non non, juste du XML, bien formaté et bien formalisé, par un organisme indépendant comme il se doit (devinez ... le W3C). Vous trouverez le fichier PersonPet.xsd plus-haut, et la normalisation de XSD à cette adresse. Jetez un oeil pour comprendre comme ça marche, et que ça ressemble bien à quelque chose d'universel.

retour à l'index

Validation

XML c'est fantastique, mais rigide : c'est la contre-partie. Il faut pouvoir vérifier de la bonne forme du document et de sa validité par rapport à "ce qu'on aurait attendu".
  • On dit qu'un document XML est bien formé, s'il ne comporte pas de caractères invalides, si les balises sont bien imbriquées, si les balises ouvertes sont fermées, si la casse est respectée et s'il n'y a qu'un seul élément racine. Par contre il peut contenir de âneries inénarrables ...
  • On dit qu'un document XML est valide, s'il est bien formé ET qu'il correspond à un formalisme pré-définis. Ce dernier peut être un document DTD ou XSD, et peut soit être inclus dans le document soit être référencé dans ce dernier.
Pour formaliser, vous avez 3 options :
  • DTD : Définition de Type de Document, normalisé par le W3C. Plus complexe à produire que l'XSD, mais est lui aussi écrit en XML.
  • XSD : comme expliqué plus haut, XSD est utilisé pour définir des schémas relationnels, c'est à dire des types de données. Bingo, avec ça, vous pouvez vérifier la validité d'un document !
  • Relax NG : créé par Oasis, solution qui semble un peu en marge des outsiders DTD & XSD, mais prônés par certains.
Si vous voulez en savoir plus sur la validation :
  • Vous trouverez chez A List Apart, un exemple d'utilisation d'XSLT. Vous trouverez un chapitre sur la validation de document XML, où il présente comment utiliser Relax NG.
  • De même sur le site W3Schools un très bon tutoriel et référence sur XSD à l'url suivante ...
  • TP OutilGL 1 où je présente XML et les WebServices, et dans le TP on passe notamment par la création d'un schéma XML (XSD) et où l'on utilise un mini outil de validation de document XML par une XSD

retour à l'index

SOAP

Simple Object Access Protocol est une technologie permettant de décrire de manière textuelle, formalisée (devinez ... le W3C) et formattée (devinez ... en XML) des objets. C'est de la "sérialisation XML" (pour ceux qui connaissaient la binaire). Et au lieu d'avoir une suite d'octets infâmes et surtout, incompréhensible et propriétaire (le langage et l'OS) vous obtenez un splendide sonnet d'informaticien.
C'est pas forcément plus lisible pour des humains (quand même un peu :), mais c'est universel car indépendant des carcans de l'OS et du langage, et les machines se débrouillent très bien avec (pour peu qu'on leur fournisse le mode d'emploi). Evidement, on perds du temps à parser du SOAP pour déserialiser un objet, mais c'est le prix à payer. Du coup, maintenant votre joli objet/appel sur votre machine peut se retrouver SANS PROBLEME sur une machine ayant un autre OS et utilisé par un programme écrit dans un autre langage.

SOAP et XML tiennent le rôle du latin au moyen-âge, ou de l'anglais de nos jours : c'est (peut-être) grâce à eux que aujourd'hui (enfin, demain), tout le monde pourra communiquer. Par contre, cela passe par l'acceptation de ce protocol par des grands qui seront en mesure de le soutenir ... et ça a l'air en bonne voie.

C'est grâce à SOAP que les WebServices existent. Rajoutez des moyens de formaliser les échanges, une politique pour gérer les transactions, la publication et les erreurs et vous obtenez les WebServices.

En plus de toutes les raisons invoquées ci-dessus, SOAP est un protocol "poids-léger". Cela signifie qu'il se greffe à l'intérieur d'un autre, sans demander de modificiations conséquentes de votre architecture (c'est aussi appelé tunnelling). SOAP "passe" par le protocol HTTP (mais ce n'est pas une obligation, voir plus bas) et est décrit au format XML, ce qui lui permet de passer au travers des firewalls (qui laissent les connexions web passer); en effet, les protocoles genre DCOM ou CORBA (binaires) sont interdits par les firewall qui ne laissent généralement rien passer d'autre que des connexions HTTP.

Pour des informations complémentaires, et une présentation sympathique de SOAP, je vous conseille cet article "SOAP pour les nuls" chez Builder.fr.

retour à l'index

Un programme utilisant XML

Le programme présenté ici n'est qu'un petit exemple : il gère une collection de DVD (stockée dans un fichier XML), et les affiche avec une DataGrid en chargeant le XML dans un DataSet. Il n'est pas exempt de bug, a très peu de fonctionnalités, une ergonomie approximative : bref, il ne sert qu'à illustrer mon propos ! Les sources sont disponibles et c'est du même pas GPL : c'est de l'abandonware :) !
Cliquez pour télécharger Cliquez ici pour obtenir le source du programme de "gestion" de DVD-thèque (fait avec VS.NET).
Cliquez pour télécharger Cliquez ici pour obtenir l'exécutable .NET correspondant.

Comme ennoncé plus haut, ce programme sert à gérer une DVD-thèque. J'en ai aussi profité pour re-montrer comment il est facile de manipuler des bases de données (ou assimilés) avec .NET, au moyen des DataSet. Le DataGrid dans lequel les informations sont affichées permet sans aucune intervention du programmeur de trier, afficher joliment, parcourrir les DVD de ma (votre ?) DVD-thèque.

Capture d'écran de DVDTheque

Capture d'écran de DVDTheque


Voici la manière dont les données sont stockées dans le fichier XML (de manière abstraite et de manière concrète) :

L'arborescence du fichier DVDTheque.xml

L'arborescence du fichier DVDTheque.xml



Le contenu du fichier DVDTheque.xml

Le contenu du fichier DVDTheque.xml


La classe que vous utiliserez pour manipuler vos fichiers XML est XmlDocument (cf .NET Documentation). Une instance de cette classe représente un document XML (comme son nom l'indique), et c'est à partir d'elle que vous manipulerez vos informations. Vous remarquerez que cette classe est une sous-classe de XmlNode - cf Doc .NET - qui représente un noeud / élément XML. Ceci est en correllation avec le fait qu'un document XML est, comme écrit plus haut, un seul élément (même si c'est une collection). On retrouve bien ici une définition reccursive (tenant à la nature arborescente du XML).

Il existe différentes manières d'utiliser du XML avec .NET, en ceci en est une. Ce programme étant minimaliste, j'ai voulu montrer qu'on pouvait réutiliser d'autres classes du framework pour se faciliter la vie. Ainsi, l'affichage se fait dans une DataGrid dont on a lié le contenu au XmlDocument grâce à un DataSet et un XmlNodeReader.
1:
2:
3:
4:
5:
6:
7:
DataSet ds = new DataSet();

XmlNodeReader xnr = new XmlNodeReader(xmldoc);

ds.ReadXml(xnr);

dgDVDs.DataSource = ds;
Les lignes 1 à 3 servent à déclarer un DataSet et un XmlNodeReader, le dernier servant à remplir le premier à partir d'un XmlDocument (ici xmldoc).
Ligne 5, on rempli le DataSet.
Ligne 7, le lien est effectué entre le DataGrid (ici dgDVDs) et le DataSet.

On peut donc en 3 lignes (en tassant un peu) lire un fichier XML et afficher son contenu comme s'il venait d'une quelconque base de donnée. Et on a les bénéfices des composants utilisant ADO.NET : très simple à utiliser, les en-têtes des colonnes sont automatiques, avec le DataGrid on a un tri automatique, etc ... Bref, un résultat "quasi pro" (on peut quand même se fouler un peu plus :) pour un effort minimal.

retour à l'index

Un programme utilisant SOAP

Un simple programme qui permet de dessiner des carrés sur une zone, les sauver et les charger. L'intérêt, c'est qu'évidement ça se fait au format XML.
Cliquez pour télécharger Cliquez ici pour obtenir le source de sérialisation SOAP (fait avec VS.NET).
Cliquez pour télécharger Cliquez ici pour obtenir l'exécutable .NET correspondant.

Capture d'écran de SoapSer

Capture d'écran de SoapSer


Les carrés sont des struct et ils sont stockés dans une instance d'une classe TRectangleCollection. C'est cette instance qu'on sérialize en XML. La seule différence avec une sérialisation en binaire (comme utilisée pour Agandah dans le cours numéro 2) tient en la nature du serializateur.

SoapFormatter ser = new SoapFormatter();

fout = new FileStream(where.FileName, FileMode.Create);

ser.Serialize(fout, Rectangles);
	

Pour plus d'informations : SoapFormatter Class.

retour à l'index

Partie 3 : WebServices

Comment marchent les WebServices

Pourquoi les WebServices

Comment faire communiquer des programmes tournant sur des machines distantes, des OS différents, développés par des compagnies différentes ? Comment dans ce cas de figure faire du remoting ? A moins d'utiliser des nombreux ponts qui existent, c'est quasi impossible. Bien evidemment, des ébauches de solutions ont été apportées et ont fait leur preuve (CORBA, COM, DCOM, ...)

Pour remettre une couche sur le débat Java vs. C#, Java avait son RMI (Remote Method Invoking) qui était certe simple à utiliser, mais qui n'était pas énormément portable. Il fallait avoir un serveur RMI qui tournait, s'enregistrer auprès de lui, éviter les firewall ou pleurer auprès de l'admin reseau pour qu'il veuille bien autoriser vos numéros de ports, c'était "sérializé en Java" donc pas compatible nativement avec les autres langages, etc...
Les WebServices (technologie NON PROPRIETEE DE MICROSOFT ) sont eux universels : encodés en XML, suivant le protocol SOAP, le tout développé par le W3C (réputé sans parti pris). Pas besoin de serveur RMI, un serveur HTTP suffit ... et le HTTP est largement plus intégré que le RMI dans les différents langages. De plus le HTTP passe sans peine par un firewall ...

Bref : C# & .NET = 1, Java = 0 ;)



Firewall

Le Firewall est souvent un problème



Idee

Firewall : comment le contourner ? En faisant une sorte de tunneling


L'utilisation d'un WebService peut se diviser en différentes étapes :
  1. On demande au WebService son contrat WSDL (Web Service Description Language) : c'est un document formalisé (rebelotte : XML, W3C, pointeur) qui spécifie quels sont les méthodes pouvant être appelées sur ce WebService.
  2. Il le retourne, et on le mémorise comment il marche (méthodes, format des appels, paramètres, valeurs retournées, etc...). Pour cela, on crée ce que l'on appelle en Java un classe stubs (souche). En C# et sous .NET, le terme consacré est classe proxy : généré par l'outil wsdl.exe, c'est une classe qui présente les mêmes méthodes que le WebService, et qui permet de les appeler de manière synchrone ou asynchrone. Par curiosité, je ne peux que vous enjoindre à jeter un oeil au code généré pour vous ...
  3. A l'utilisation : on appel la méthode (SOAP+XML) désirée conformément au format précédament acquis. Et ceci, tout simplement en instanciant la classe proxy et en utilisant ses méthodes. C'est transparent.
  4. On récupère le résultat de la méthode, ou une erreur. Je vous souhaite le résultat :), mais une erreur sera levée si le schéma WSDL du WebService a changé !

Etapes

Les étapes de l'utilisation d'un WebService



Les WebServices passant (sauf si vous en décidez autrement) par HTTP peuvent utiliser d'autres protocols que SOAP pour transporter des données. Mais ceci implique des restrictions, ennoncées ci-dessous :
Quoi POST GET SOAP
Transporter des types primitifs (Integer, Long, String, ...)
Transporter des énumeration
Transporter des tableaux (d'énumeration ou de primitifs)
Objets
Structures
DataSets, fichiers XML, tableau de n'importe quoi
Passage par référence
NB : GET et POST sont les méthodes de passage de valeur propres à HTTP.

retour à l'index

HTTP et SOAP sont obligatoires ?

Rappelons que SOAP n'est qu'un protocol implémenté par un formatteur dans .NET (cf SoapFormatter dans Doc .NET).
Si vous souhaitez améliorer les performances de votre WebService, vous pouvez vous passer de SOAP. En effet, on perd beaucoup de temps en formattage/deformattage : comme SOAP est un protocol poids léger, textuel, il faut le parser pour deserialiser. Et même si l'on vous assurera que "c'est optimisé, et que cela va super vite" cela coûte toujours plus cher que de passer par une sérialisation binaire.

Comment faire ?
  • Dans l'idée : faire un peu plus de travail à la main, instancier notre formatteur binaire, etc.
  • Dans la pratique : il suffit d'indiquer dans le fichier de config de votre client (typiquement mon_programme.exe.config, au format XML) dans l'élement <formatter /> l'attribut ref="binary".
    ( conférence TechEd 2002 par Brad Merrill DEV341 + .NET doc Remoting Example ...).
Et vous pouvez même redescendre dans la pile protocolaire et vous passer de HTTP ! Simplement, vous utilisez TCP directement, et le gain est sensible (surtout si couplé à un formatteur binaire). Vous obtenez un gain de l'ordre du triple/quadruple au niveau du transfert.
Pour en savoir plus sur les fichiers de configuration sous .NET, Configuration Files dans l'aide .NET.

Attention toutefois : ce gain a un dèsavantage (sinon, s'aurait été le mode de base). Si vous formattez en binaire, fini la belle universalité des WebServices (cela marchera encore entre .NET/.NET mais oubliez l'interopérabilité). Et si vous utilisez TCP (sans HTTP), de nombreux firewall ne vous laisseront plus passer.

retour à l'index

UDDI

Acronyme de Universal Description, Discovery and Integration , UDDI est en fait une technologie (un espèce d'API SOAP-esque, en XML of course) qui est une sorte d'annuaire de Web Services.
Vous emettez une requête auprès d'un site UDDI (typiquement celui de IBMtm ou celui de Microsofttm) qui est un message SOAP XML au format UDDI, et vous recevez une réponse vous indiquant quel WebServiceS correspondent à votre demande.
Ce qu'il y a d'amusant, c'est que c'est la première application des Web Services qui est au service des Web Services (dire 10x rapidement). C'est un "Web Service annuaire de Web Services".

Pour plus d'informations sur l'UDDI :

retour à l'index

Visual Studio .NET n'est pas obligatoire

Vous êtes amoureux de la liberté, du "je travaille partout et même avec debug s'il le faut" ?
Vous détestez les IDE car vous n'aimez pas qu'on fasse des choses dans votre dos ?
Vous êtes un tantinet parano ?
Vous agréez aux idées de .NET mais vous êtes un fervent défenseur des manchots ? ;)
Malgré mon tout ce que j'ai dit, vous demandez à avoir une preuve que les WebServices ne sont PAS la propriété de Microsoft ?

Bref vous avez surement un très bonne raison pour vouloir vous passer de l'excellent outil qu'est Visual Studio .NET. Et bien soit, nous allons faire d'une pierre deux coup :
  • Vous montrer ce que fait Visual Studio .NET dans votre dos
  • Vous démontrer que les WebServices NE SONT PAS UNE TECHNOLOGIE PROPRIETAIRE DE MICROSOFT

Tout d'abord les outils (comme d'habitude) :
  • Un bon éditeur de texte. Pour moi, il n'y a pas mieux qu'Emacs ;)
  • Un IIS à la maison avec le .NET Framework installé pour faire tourner mes WebServices.
  • Un invite de commande.
  • Vous (au travail !).

Bien évidemment je traiterai aussi comment faire des WebServices avec VS.NET, mais c'est à la main que c'est le plus instructif. C'est par là que je commencerai donc.
Nous allons voir plusieurs aspects. Pour commencer, je vais consommer (c'est le terme consacré) un WebService Microsoft .NET avec un programme Microsoft .NET. Puis je le consommerai en Java (vous verrez, ça marche aussi avec les outils du voisin). Et puis on inversera les rôles avec GLUE (version Java des WS, gratuit en version standard).

retour à l'index

WebService .NET / Client .NET

Cliquez pour lire
Cliquez ici pour lire le TP RMI vs. WebService qui explique autrement comment utiliser des WebServices pour faire du .NET/NET.
Cliquez pour télécharger
Cliquez ici pour obtenir le source de mon WebService exemple (KryptoService : permet de crypter/décrypter un string avec DES 64 bits).

Créer et installer un WebService

Je conseille vivement d'avoir bien lu le cours précédent sur ASP.NET car il y a éNORMEMENT de similitudes entre la création d'une WebForm et d'un WebService.

Comme pour les WebForms on retouve ici les mêmes notions : la paire de fichier (dissociation page/code), les assemblies, l'intégration IIS.
La Paire
Vous aviez en ASP.NET un fichier toto.aspx et toto.aspx.cs. Pour les WebServices, vous avez toto.ASMX et toto.ASMX.CS (ce n'est qu'une convention, tout autre nom de fichier .CS sera valide).

Voici ce à quoi doit ressembler votre toto.asmx (toute ressemblance avec le cours précédent sur ASP.NET est strictement voulue) :
<%@ WebService CodeBehind="toto.asmx.cs" Class="MonProjet.MonWebservice" %>
  • <% et %> : ce sont des chevrons ASP (ce qui est entre doit être traité par IIS avant envoi au client)
  • @ WebService : chevron ASP.NET (signifie juste que c'est un WebService en ASP.NET)
  • CodeBehind : Spécifie où se trouve le code source pour cette page. Cet attribut n'est pas necessaire : ce n'est utilisé que quand ASP.NET ne trouve pas d'assembly contenant la classe spécifié; le fichier définit comme CodeBehind est alors recompilé à la volée par ASP.NET.
    Si vous têtu et que vous voulez faire du code inline remplacez ce chevron par Language="C#" et tapez votre code simplement à la suite (pas de HTML ici).
  • Class : Quelle classe du projet représente le WebService. Comme toujours, [Namespace.]*Class .
Vous trouverez la liste complète des attributs dans la documentation .NET Framework @ WebService.

Et voilà pour le fichier .asmx. Pour le fichier .asmx.cs c'est un fichier C# tout ce qu'il y a de standard. Essayez un truc sympa : prenez un de vos fichier/programme C# et tranformez le en WebService en 1 minute.
La seule différence réside dans le fait que certaines méthodes portent l'attribut [WebMethod]. Eh oui, car comment allait faire votre WebService pour savoir quelle méthodes il devait publier ? On ne lui avait rien dit. Ainsi, vous dites quelle sont les méthodes accessibles de l'extérieur. Rien ne vous empêche d'avoir plein de méthodes privées ou d'utiliser d'autres fichiers C#. Vous êtes entièrement libre : c'est une classe comme une autre !!!

Une signature de WebService (kilébo mon Emacs :)

Une méthode publiée par le WebService


NB : la classe de votre WebService peut hériter de la classe System.Web.Services.WebService et ainsi avoir accès aux objets ASP.NET (Request, etc...). Ceci n'est PAS obligatoire et est inutile dans notre cas.

Voilà pour le boulot concernant la création d'un WebService. Il est créé, il faut maintenant le compiler et l'installer sous IIS.
Installer et configurer
On passe par IIS car les WebServices quand ils passent par HTTP on besoin ... d'un serveur HTTP. L'installation dans IIS permet aussi la mise en place du HTTPhandler, lancé par le filtre ISAPI de .NET : quand une requête arrive sur un WebService .NET par IIS par un browser Web, le HTTPhandler génère à la volée les jolies pages que vous voyez ci-dessous.

C'est quasiement la même marche à suivre qu'avec ASP.NET. On crée un répertoire dans le répertoire de base des pages IIS (typiquement C:\INetPub\wwwRoot\). On copie les fichiers .asmx et .cs dedans. On crée un sous-répertoire bin\. et on compile tout le monde ! (dans notre exemple, on utilise un autre fichier C# donc on le compile aussi).
La DLL assembly vers laquelle on compile ne dois pas porter de nom particulier : ASP.NET se débrouille pour la trouver, tant qu'elle est au bon endroit.
csc /out:bin/KryptoService.dll /t:library alkryptws.asmx.cs alkryptoker.cs 
Pour les explications, ce sont les mêmes que dans le cours ASP.NET.

Ensuite, même combat : on dit à IIS de "faire une application" sur notre répertoire, et on va faire un tour sur http://localhost/le-projet/monwebservice.asmx (ici, ce serait http://localhost/KryptoService/AlKryptWS.asmx). Et on tombe sur une page dans le genre suivant :

Cliquez pour voir un exemple html

Le résultat de l'accès en HTTP au WebService


Et oui, on trouve une belle page générée automatiquement par ASP.NET. Ce dernier dispose en effet d'un HttpHandler par défaut s'occupant de générer ces belles pages en cas d'accès par http. Vous pouvez même tester vos propres WebServices ! Cliquez sur la méthode qui vous interresse et entrez des valeurs. Vous recevrez ensuite une page xml contenant le résultat.
Dans mon exemple, l'appel à Bonjour avec Alain comme paramètre donne :

L'appel par le HTTPHandler de la méthode du WS


Le résultat XML de l'éxecution d'une méthode du WebService


Et maintenant, on va consommer le WebService. C'est un tout petit peu plus compliqué que de le créer (à la main) mais c'est fait en 2 minutes.

Consommer avec .NET un WebService .NET

Cliquez pour télécharger Cliquez ici pour obtenir le source de mon "consommateur" en .NET de notre WebService .NET exemple.

Voilà. Vous avez un beau WebService maintenant. Et vous avez envie de l'utiliser ? Facile. Il suffit de lui envoyer un message à un certain format, et de le réceptionner ... en sachant le décoder. Mais comment faire tout ça ?
La solution : dans la vie, faut pas s'en faire (comme disait la chanson). .NET est là et fait TOUT (ok, presque tout) le boulot pour vous. Que ce soit de générer le contrat WSDL (que fait le WebService, comment, qu'est ce qu'il retourne, etc...) ou le marshalling (correspondance des types, conversion, ...). Vous n'avez rien à faire, ou presque.
Eh oui, il faut bien dire à .NET que l'on veut utiliser CE WebService. En effet, pour l'utiliser on a seulement besoin de savoir ce qu'il fournis "au format C#" dans notre cas. On a besoin de connaître les types exposés, les méthodes, etc... Et c'est justement ce qui est dans le contrat WSDL, mais en XML. La solution est de créer une classe proxy qui contiendra tout cela. Ce sera un objet C# accessible dans notre projet de manière transparente !

On va le faire en 2 étapes :
  1. Fabriquer une classe proxy (un .cs ou .vb)
  2. Compiler cette dernière dans une assembly
1/ Classe proxy
On la génère par la ligne suivante (dans notre cas) :
wsdl http://localhost/KryptoService/AlKryptWS.asmx?WSDL /language:CS 
                                    /namespace:KryptoWS /out:KryptoWS.cs
  • wsdl : c'est le programme (venant avec .NET Framework) qui créé une classe proxy à partir d'un contrat WSDL
  • http://localhost/KryptoService/AlKryptWS.asmx?WSDL : l'URL du contrat WSDL à partir duquel travailler. Remarquez que pour l'obtenir on ajoute ?WSDL à la fin de l'URL du WebService
  • /language:CS : on veut un fichier en C# (VB pour VB.NET)
  • /namespace:KryptoWS : quel sera le Namespace dans lequel créer le proxy
  • /out:KryptoWS.cs : le nom du fichier à créer
Après exécution, on obtient un fichier (dans notre cas toujours) de quelques kilo-octets. Vous pouvez y jeter un oeil, mais sachez que sa compréhension n'est pas nécessaire pour consommer le WebService. Il contient en fait une sous classe de SoapHttpClientProtocol, qui vous permettra entre autre, d'appeler de manière synchrone ou asynchrone les méthodes du WebService. (nous utiliserons la version synchrone) On n'a plus qu'à l'inclure en ajoutant dans nos directives using :
using KryptoWS;

2/ Classe proxy vers Assembly
Vous n'avez qu'à instancier votre WebService pour pouvoir utiliser ses méthodes comme si c'était un objet provenant d'une assembly locale ! Voici ce que cela donne dans notre exemple :

Cliquez pour télécharger les sources

Quelques lignes pour consommer un WebService


Ensuite, rajoutez simplement KryptoWS.cs (notre fichier contenant la classe proxy) parmis les fichiers à compiler. Et voilà le résultat :

La sortie de notre programme

Le résultat de l'utilisation du WebService de cryptographie



retour à l'index

WebService .NET / Client Java

Cliquez pour télécharger Cliquez ici pour obtenir le source de mon consommateur de WebService .NET en Java.
Nécessite GLUE.
Visitez The Mindelectric et téléchargez GLUE Standard GLUE permet d'utiliser les WS en Java, disponible gratuitement en version standard chez The MindElectric.

Ce cours étant sponsorisé par Microsoft France, et par conséquent, je ne vais pas m'attarder sur "comment faire pour utiliser/créer un WebService en Java" ;). De très bon tutoriaux sont sur le Web et expliquent cela parfaitement. Par contre, je montrerai rapidement que l'interopérabilité Java/.NET EXISTE et que les WebServices SONT UNIVERSELS.

Mise en place

Comme expliqué plus haut, vous devez avoir installé sur votre ordinateur un JDK (récent) et GLUE. L'installation se passe sans problème et les deux sont indépendants l'un de l'autre. Configurer GLUE après installation est fait en 2 minutes et est fort bien expliqué dans l'aide de GLUE (cela revient à changer le CLASSPATH et c'est tout).

À ce point, c'est à nouveau le même combat : générer une classe proxy, utiliser, compiler, lancer.

Générer la classe proxy

Tout ceci est clairement expliqué dans la doc de GLUE (section GLUE User GUIDE - Basics - Invoking)

Cela se fait avec le programme venant avec GLUE qui se nomme wsdl2java (dure de faire plus explicite). La génération de la classe proxy se fait en une ligne, non détaillée car il n'y a rien à détailler :
wsdl2java http://localhost/KryptoService/AlKryptWS.asmx?WSDL
Vous obtiendrez ainsi 2 fichiers : IMonWebServiceSoap.java qui contient une interface identique à celle proposée par votre WebService, et MonWebServiceHelper.java qui est une sorte de factory qui permet de créer une "instance" de votre WebService.
Dans notre cas, les deux fichiers générés sont IAlKryptWSSoap.java & AlKryptWSHelper.java.

Consommer

Cela se fait en 2 lignes. Typiquement, on crée une instance de notre classe Proxy (stubs pour les Java-istes) avec le Helper et on appel la méthode (si le WebService n'était pas instancié pour des raisons de politiques de gestion de ressource du serveur HTTP, un représentant de notre WebService est instancié) . Fini.
Voici un exemple dans notre cas :

Utilisation de notre WebService en Java (cliquez pour télécharger)

L'utilisation en Java du WebService .NET de cryptographie


Ne surtout pas oublier un import important (celui des classes de GLUE) :
import electric.registry.Registry;
Et voilà le résultat :

La sortie de notre programme

Le résultat de l'utilisation Java du WebService .NET de cryptographie


NB : vous pourrez remarquer (à juste titre) que le client java consomme le WebService, mais pas les même méthodes que celles utilisées par le client .NET. En effet, le WebService propose 2 couples de méthodes de crypto : une rendant/utilisant des String, l'autre des char[]. .NET supporte les 2 mais pas GLUE.

GLUE (wsdl2java.exe plus précisément) signale une erreur dans le contrat WSDL du WebService pour les méthodes utilisant/rendant des char [] (alors que .NET accepte) : par conséquent, pas de classe proxy générée. Par contre, il peut très bien utiliser ceux rendant des String mais ces derniers lèvent des exceptions ... Il faut donc avoir 2 WebServices : un pour Java, l'autre pour .NET. Encore un petit problème d'incompatibilité qui force à jouer avec nos WebServices:(.
Bien entendu, il existe des méthodes pour contourner le problème, mais il est interressant de remarquer que l'utilité d'une technologie tient pour beaucoup à ses implémentations.;)

Toutefois, la liste des types supportés par GLUE est importante. Pour info, vous trouverez la trouverez dans l'article Interopérabilité entre WebServices .NET et Java (chez DotNetGuru). La compatibilité Java/.NET/"reste du monde" par les WebServices reste grande : certaines implémentations on juste besoin de mûrir. Les WebServices restent à mon sens aujourd'hui la meilleure manière de faire du client serveur (et bien plus) sous .NET (évidement) mais avec les autres langages et OS.

Conclusion : Interopérabilité WebServices .NET & client Java avec GLUE = 18/20 . Très bien pour des types simples, mais certaines fautes noircissent le tableau. Il faut que l'implémentation GLUE murisse encore un peu. Peut mieux faire.


retour à l'index

WebService Java / Client .NET

Cliquez pour télécharger Cliquez ici pour obtenir le source de mon WebService 'Dice' en Java.
Nécessite GLUE.
Cliquez pour télécharger Cliquez ici pour obtenir le source de mon consommateur de WebService Java en .NET.
Visitez The Mindelectric et téléchargez GLUE Standard GLUE permet d'utiliser les WS en Java, disponible gratuitement en version standard chez The MindElectric.

Créer et consommer un WebService Java

C'est l'enfance de l'art. Tout d'abord créez un WebService en Java à l'aide de GLUE. C'est fait en 1 minute, et c'est très bien expliqué dans la doc de GLUE (section GLUE User GUIDE - Basics - Publishing). Vous avez deux choses importantes dans votre fichier : les import qui changent et la manière de publier (ultra-simple).
Ici, mon service s'appelle Dice et est représenté par la classe Dice.java. Il simule le lancement d'un dé à n faces et retourne le résultat.

2 import à penser

Les imports


La publication

Publier son WS Java en 2 lignes


Pour récupérer le contrat WSDL c'est fait à l'adresse http://localhost:8004/glue/Dice.wsdl . D'où maintenant on créé notre classe proxy .NET comme suit :
wsdl http://localhost:8004/glue/Dice.wsdl /language:CS /namespace:DiceWS /out:KryptoWS.cs
Et le reste, c'est EXACTEMENT PAREIL qu'avec un WebService .NET !!! D'ailleurs pour le prouver, je n'en parlerai même pas !! Lisez plus haut, section WebService .NET / Client .NET ou lisez le source.

Consommation de Java par .NET


Quand on lance le WS Java

Le WebService Java est lancé


La consommation

Résultat de la consommation de notre WebService Java


retour à l'index

Et avec Visual Studio .NET

Maintenant que vous savez quel est le boulot qu'il y a à faire pour fabriquer votre WebService à la main : oubliez ! Non, n'oubliez pas, mais laissons ces tâches - pas forcément ultra productives - à une machine qui fera moins de fautes de frappes que nous. Et ce merveilleux item est VS.NET.

Je ne présenterai pas "comment créer son WebService avec VS.NET" car vous ne pouvez pas vous tromper ! C'est impossible ! File / New / Project ... / C# / ASP.NET Web Service et c'est tout fait pour vous. Vous n'avez qu'à taper votre code.

Je vais par contre présenter comment consommer un WebService (NB : un WebService peut en consommer un autre, évidemment) avec VS.NET.

Consommer un WebService avec VS.NET

Cliquez pour télécharger Cliquez ici pour obtenir le source de mon consommateur VS.NET du WebService 'Dice' en Java.

Nous allons consommer mon WebService Java (si après ça vous croyez encore que les WS sont propriétés Microsoft, je renonce). Voilà comment, en image :

1/ Il faut d'abord lancer le Web Service.

On lance le WebService

On lance le WebService Java (encore faut-il y penser !! :)


2/ Ensuite, dans Visual Studio .NET, lancez l'assistant d'ajout de référence Web :

On lance l'assistant d'ajout de référence Web

On lance l'assistant d'ajout de référence Web


L'assistant d'ajout de référence Web

L'assistant d'ajout de référence Web


3/ Tapez dans la zone prévue à cet effet l'URL du contrat WSDL du Web Service convoité. Validez par <Entrée>, et si après quelques secondes le contrat WSDL apparaît dans le volet de gauche, et que le bouton Add reference est accessible : c'est bon. VS.NET vient de vérifier que le contrat WSDL est valide, et il vous autorise à inclure le Web Service dans votre projet.

Le WebService est utilisable

L'assistant d'ajout de référence Web accepte le WebService


4/ La nouvelle référence apparaît dans l'arborescence de votre projet VS.NET. Vous remarquerez que le nom de l'assembly sont ceux de l'URL inversés : ainsi, un WebService chez www.microsoft.com serait dans l'assembly com.microsoft.www. Vous pouvez bien entendu changer cela ... La classe proxy pour ce WebService vient d'être générée et enregistrée dans votre projet.

La nouvelle arborescence du projet

Le WebService a été référencé dans notre projet


5/ Vous pouvez maintenant vous en servir librement. Soit en nommant complètement l'objet que vous instanciez (comme dans notre exemple) ou vous pouvez ajouter l'assembly du proxy dans les clauses using.

2 lignes de codes pour utiliser le WebService

Les 2 lignes nécessaires pour utiliser le WebService


6/ Et voilà le travail ! Un programme Microsoft .NET qui utilise un WebService, et ceci de manière transparente pour l'utilisateur. Ce dernier doit toutefois avoir accès au WebService (login, pwd, connexion reseau,...).

Un joli programme de lancé de dés

Mon programme de lancé de dés



retour à l'index

Partie 4 : Le mot de la fin

Conclusion

A l'origine, ce cours devait *simplement* présenter les WebServices, comment les utiliser et expliquer leurs principes. Mais je me suis bien vite rendu compte qu'essayer de les expliquer correctement sans parler de XML était impossible. Parler d'XML n'est pas une mince affaire dans .NET où il apparait très souvent, et où il tient une place de choix. Parler de manière interressante d'XML ne pouvait non plus se faire sans parler XSD, XSLT et autre que j'ai découvert tout au long de la rédaction de ce cours. Voilà pourtquoi ce cours dont j'ai commencé la rédaction en même temps que le cours #3 sur ASP.NET m'a pris 6 mois pour être fini.
J'espère que ce cours a suffit à présenter de manière sommaire (pour certains points du moins) "A quoi servent les WebServices et comment en fait-on avec Microsoft .NET ?". Je souhaite aussi vous avoir interressé à XML qui est (car il est nanti de technologies connexes très puissantes) une technologie des plus interressante, et à la fois des plus naturelle que j'ai manipulé.
Bref : "perso, XML c'est d'la balle".

retour à l'index

Remerciements

Monsieur Laurent ELLERBACH, responsable relation études supérieures chez Microsoft France, pour ses idées et son soutien logistique.
Mesdames Anne-Marie DERRY-PINNA et Mireille BLAY-FORNARINO, professeurs à l'ESSI, pour leurs encouragements.

retour à l'index

Sources

Sur le Web : Bibliographie :
  • Formation à ASP.NET (poche, pas cher, très bien) ISBN : 2-84082-865-0 chez MSPress (et sur le web www.c2i.fr/press)
  • Manuel de référence XML (cher, EXCELLENT !!, couvre beaucoup de domaines) ISBN : 2-10-006520-3 chez MSPress
  • Designing Microsoft ASP.NET Applications (cher) ISBN : 0-7356-1348-6 chez MSPress

retour à l'index

 




par Alain Vizzini (vizzini@essi.fr )
pour l'ESSI & Microsoft, création 07-04-2002, dernière màj 25-02-2003


pages vues depuis le 14 oct. 2002