Cours de C# pour l'ESSI - ESSI2 Reseau - TP1 revisited

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



Partie 1 : Introduction

Je rappellerai à mon aimable lecteur(trice) que ce cours est sponsorisé par Microsoft France. Par conséquent ce sont bien évidement des technologies développées ou utilisées par Microsoft (mais qui ne sont pas forcément sa propriété) que je présenterai ici.

Le but est ici de présenter le pendant du TP1 du cours de Réseaux de 2ème année de l'ESSI où nous avons (ESSIens) appris à utiliser RMI (Remoting Method Invoking) avec Java. C'est notamment par ce moyen là que Java "fait" du Client-Serveur, objets répartis, etc ...
Il existe peut-être (libre aux curieux de chercher) des portages de RMI vers d'autres langages, voir même vers C# et le monde .NET. Ceci ne sera pas présenté ici. Je vais m'efforcer de présenter de manière SIMPLE mais SUFFISAMENT DETAILLEE comment faire du Client-Serveur avec C#. Nous allons utiliser les WebServices pour cela.

Je tiens tout de suite à préciser une chose IMPORTANTE : les WebServices ne SONT PAS les équivalents de RMI. RMI est FORTEMENT connecté, les WebServices sont FAIBLEMENT connectés. C'est à dire, si vous utilisez un web service, le lien entre votre client et le WebService n'existera que le temps de l'appel-réponse. En RMI, votre connexion dure plus longtemps (elle n'est pas limitée à un seul échange). Si vous voulez utiliser le pendant de RMI qui est .NET Remoting, alors dirigez vous vers cette page : "RMI vs. .NET Remoting".

Bien que les noms et technologies soient différentes, les concepts sont les mêmes (ils sont rappelés section Concepts). Vous retrouverez de la sérialization, des stubs (en .NET, ce sont des proxy), etc... Bien entendu, il y a des différences !! (sinon Microsoft n'aurait eu aucun mérite en plagiant ce qui était fait en Java) Et ces différences vous seront expliquées le plus simplement possible (sans rentrer dans les détails) ;).

Ce premier TP est relativement cours, et vous pourrez le faire en 1h, si vous avez compris ce que vous avez fait en Java.

Il est plus que conseillé de se référer à la présentation C# vs. Java (SURTOUT si vous n'avez jamais fait de C#) ainsi qu'aux autres cours en cas difficulté. Notamment le cours sur les WebServices !!!
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 : Concepts

Tout ce qui est expliqué dans cette partie l'est aussi, dans un cadre plus large et plus en détail, dans le cours XML & WebServices. Il est interressant de se référer aux deux pour avoir une bonne compréhension du vaste sujet des WebServices. Toutefois, ce TP-ci, explique plus longuement comment faire des WebServices avec .NET.

En Java, c'est par RMI que passe les appels de méthodes distant. Un serveur RMI (rmiregistry) tourne sur votre machine, où il joue le rôle "d'annuaire de service". Vous devez connaître le nom du service auquel vous désirez accéder, et évidement son interface. Quand votre requête aboutit, vous passez par une classe souche (ou stubs) pour invoquer les méthodes de l'objet distant. La sérialisation est en binaire, ou plutôt en "natif Java".

Les WebServices avec .NET


En C# (et .NET) c'est à peu près la même chose. Vous publiez votre WebService au moyen de votre serveur IIS (Internet Information Server, le serveur HTTP/FTP/... de Microsoft) ou de n'importe quel serveur HTTP supportant les WebServices .NET (ceci inclut n'importe quel micro serveur HTTP que VOUS pourriez écrire). Pour faire simple, on fera cela avec IIS.
Vous adressez vos requêtes à l'URL du WebService : comme nous passons par HTTP dans notre cas, l'URL est "http://le-serveur/un-chemin/le-webservice". Notez bien que ce n'est pas du protocol RMI mais du HTTP. Les appels de méthode, et le renvoi de résultats se font au format SOAP (un protocol décrit en XML). SOAP est un protocol "poids-léger" qui "passe par" HTTP. Simplement ? Si vous connaissez HTML, vous avez une idée de ce qu'est SOAP ! Des balises, imbriquées suivant un formalisme TRES CLAIREMENT et PUBLIQUEMENT définis, qui servent à décrire des objets, attributs, méthodes, etc... Par conséquent, si vous (langage X) savez comprendre du SOAP, vous savez utiliser les WebServices, .NET ou non.
Vous possédez bien sur une classe proxy (équivalente à la classe stubs), mais générée à partir de ce que l'on appel schéma WSDL. Ce schéma est généré automatiquement par le WebService et décrit ses capacités. Vous créez votre proxy avec l'outil wsdl.exe à partir d'un schéma WSDL. Vous trouverez ce dernier par défaut à l'URL suivante "http://le-serveur/un-chemin/le-webservice?WSDL" avec les WebServices .NET sous IIS.

Une GROSSE différence entre RMI et les WebServices, est que avec RMI vous êtes obligé de distribuer à votre client une interface Java décrivant le service proposé. Ce n'est pas difficile, mais pas très automatisé (aucun protocol ne s'en charge automatiquement). Par contre avec les WebServices, la classe proxy est générée DYNAMIQUEMENT à partir du contrat WSDL, et ne requiert de l'utilisateur que de connaitre le format de l'appel (la signature), ce qui est le minimum.

Comme en RMI, si votre WebService change par ajout de méthode, votre client reste valide. Il n'aura simplement pas accès aux nouvelles (ce qui est en soi assez évident). Par contre, si vos signatures de méthodes utilisées change, il râlera (normal aussi !!).

Pour faire des WebServices sous .NET, vous devez avoir installé sur votre poste AU MOINS :
  1. Windows XP Pro ou 2000 avec SP2 ou NT4 avec SP6a
  2. Internet Explorer 5.01
  3. IIS
  4. .NET Framework SDK
  5. un éditeur de votre choix (emacs ou VS.NET suivant les courants de pensée)
Bonne prog! Il vous faut je pense une heure pour faire ce TP si vous avez compris RMI et que vous n'êtes pas effrayé par C# (qui ressemble énormément à Java je rappelle).

retour à l'index

Partie 3 : Pratique

Cliquez pour télécharger Cliquez ici pour obtenir le .NET Framework SDK (130 Mo).

WebService (Serveur)

Cliquez pour télécharger Cliquez ici pour obtenir le source du serveur (WebService).
Le serveur est un WebService (le client peut en être un ou pas). Quelle est la structure d'un WebService ? Connaissez vous le C# ? Non ? Partont du début ...

Une classe en C#

Voici une classe HelloWorld (que d'originalité ) en C# :
/* ** fichier HelloWorld.cs ** */

using System;

public class HelloWorldWS{

  public String direBonjour (String nom){
    return "Bonjour " + nom;
  }

}
Si vous trouvez que ça ressemble à du Java, c'est pas étonnant, C# et Java venant de C++ ... ok, Microsoft s'est largement inspiré de la syntaxe Java. Mais il n'y a pas de mal ! Dites vous que 90% du C# ressemble au Java. Reportez vous au cours Java vs. C# si vous voulez connaitre mieux C#.

Un WebService C#

Dans cet exemple, nous créons un WebService que nous nommerons HelloWorldWS et qui sera dans le projet nommé HelloServiceInc car c'est pour une grosse boite américaine qui a super besoin de notre WebService.

Voici maintenant la même classe que ci-dessus, mais qui peut dèsormais être utilisée comme un WebService :
/* ** fichier HelloWorldWS.cs ** */

using System;
using System.Web.Services;

public class HelloWorldWS : WebService{

  [WebMethod(Description="Une methode qui dit bonjour")]
  public String direBonjour (String nom){
    return "Bonjour " + nom;
  }

}
Vous remarquerez que plusieurs lignes apparaissent:
  1. using System.Web.Services est le namespace contenant toute les classes utiles pour les WebServices.
  2. : WebService signifie "sous classe de WebService" (équivalent à un extends WebService en Java).
    NB : ceci est optionnel. Il n'est pas besoin de dériver de la classe WebService pour être utilisé comme WebService. Simplement, vous n'aurez pas accès aux objets ASP.NET, tel que Session, Request, etc... Ce n'est pas nécessaire pour notre WebService basic s'il en est.
  3. [WebMethod] est ce que l'on appel un attribut de méthode en .NET. L'utilisation rappelle celle des "interfaces flag" en Java, mais avec la possibilité d'avoir des attributs sur l'attribut de méthode (ici, l'attribut facultatif Description est une explication de l'utilité de la méthode et qui sera visible en accès Web au WebService; on en reparle plus bas ...). Celui-ci permet de dire que "la méthode qui suit devra être présentée au monde si cette classe est mise en service en tant que WebService". (WebMethod Attribute).

Distribuabilité

Vous avez maintenant une jolie classe qui PEUT ETRE utilisée en tant que WebService. Je rappelle, que le fait d'avoir défini l'attribut WebMethod ne change en rien le comportement "par défaut" de la classe et de ses instances. Ainsi, vous pouvez continuer à utiliser cette classe ô combien utile dans vos programme en l'état.
Pour la distribuer, sous forme de WebService (vous distribuez en fait ses actions, mais restons simples), vous allez devoir passer par IIS. Mais IIS, le serveur Web de Microsoft, n'y connais rien du tout à .NET. Comment faire pour qu'il daigne comprendre qu'on voudrait accéder à un WebService, qu'il faut gérer une instance du WebService, etc ... ? Simple : ne pas lui dire ;).
IIS utilise des filtres ISAPI (Internet Server API), technologie Microsoft, qui se présente sous la forme de DLL à brancher dans IIS en lui disant : "si tu recois une requête pour un fichier de type XYZ, previens le filtre ISAPI LAMBDA avant d'envoyer quoi que ce soit au client". Bien évidement, .NET vient avec un filtre ISAPI pour IIS, qui s'installe tout seul sans rien demander de votre part. Il est enregistré pour les fichiers ASP.NET (.aspx) et pour les "fichiers WebServices".
Il vous faut maintenant générer un fichier "le-nom-du-webservice.asmx" (pour nous, "HelloWorldWS.asmx"). Il ne contient qu'une ligne, son seul but étant de permettre le déroutement des requètes vers le filtre ISAPI de .NET. Que dit il ? Quelle classe est concernée, dans quel fichier elle se trouve. Comment le dit-il ? Comme ça :
<%@ WebService CodeBehind="HelloWorldWS.cs" Class="HelloWorldWS" %>
  • <% 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.
  • Class : Quelle classe du projet représente le WebService. Comme toujours, [Namespace.]*Class : dans notre cas, étant dans le namespace par défaut, pas besoin de préfixer. Si nous avions été dans le namespace "HelloServiceInc", on aurait eu "HelloServiceInc.HelloWorldWS".
Vous trouverez la liste complète des attributs dans la documentation .NET Framework @ WebService.

Publication

Ceci requiert que vous ayez IIS installé ET tournant sur votre machine (NB : seul le module HTTP est requis). Vous devez avoir AUSSI le .NET Framework installé (le .NET Runtime suffit pour publier, mais pas pour compiler le WebService).

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 verrez ci-dessous.

On crée un répertoire (généralement du nom du projet) 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 (sauf le .ASMX qui ne contient pas de code) !
csc /out:bin/HelloWorldDLL.dll /t:library helloworldws.cs

  • csc : c'est le compilateur C#
  • /out:bin/HelloWorldDLL.dll : nous allons produire un fichier de sortie où il faut. C'est une assembly qui contiendra les classes de notre projet. Il est de bon goût qu'il porte le nom du projet (MAIS ce n'est pas obligé, et ce n'est pas le cas dans notre exemple). Cette dernière doit TOUJOURS être dans le sous répertoire /bin du fichier .asmx.
  • /t:library : nous indiquons que nous souhaitons produire une DLL (Dynamic Link Library), par opposition à un programme exécutable.
  • helloworldws.cs : la liste des fichiers .cs à compiler.
NB : pour plus d'explications, cf le cours ASP.NET. + C# compiler option.
Vous devriez avoir maintenant cette arborescence :
c:\INetPub\wwwRoot\HelloServiceInc\
                                  HelloWorldWS.asmx
                                  HelloWorldWS.cs          (<=== FACULTATIF)
                                  bin\
                                      HelloWorldDLL.dll

Ensuite il faut dire à IIS de "faire une application" (dans le module de configuration de IIS, clic-droit sur le répertoire du projet, Propriété, Paramètres d'application / Créer) sur notre répertoire.

Voilà ! Le WebService est en place, on peut le tester.

Test

Il suffit de faire un tour sur http://localhost/le-projet/monwebservice.asmx (ici, ce serait http://localhost/HelloServiceInc/HelloWorldWS.asmx). Et on tombe sur une page dans le genre suivant :

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 à direBonjour 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


Ceci est généré par le HTTPHandler, qui prends la relève quand une connexion HTTP arrive au le WebService à partir d'un browser. Ce que vous voyez est généré automatiquement, en utilisant la réflexion sur la classe du WebService (si vous savez pas ce qu'est la réflexion, c'est le fait d'obtenir dynamiquement des informations sur une classe ou un objet).

retour à l'index

Client

Cliquez pour télécharger Cliquez ici pour obtenir les sources de notre WebService.
Cliquez pour télécharger Cliquez ici pour obtenir l'exécutable
<COPIE notabene="Ce qui suit est la même partie que celle dans le cours #4 sur XML & WebServices retouchée pour coller à l'exemple ci-dessus.">
Comment consommer le magnifique WebService de HelloServiceInc ?? En récupérant son schéma WSDL et en générant grâce à lui une classe proxy qui servira à utiliser le WebService. 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/HelloServiceInc/HelloWorldWS.asmx?WSDL /language:CS /namespace:HelloServiceInc /out:HelloWorldPROXY.cs
  • wsdl : c'est le programme (venant avec .NET Framework) qui créé une classe proxy à partir d'un contrat WSDL
  • http://localhost/HelloServiceInc/HelloWorldWS.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. C'est comme cela que l'on fait avec IIS.
  • /language:CS : on veut un fichier en C# (VB pour VB.NET)
  • /namespace:HelloServiceInc : quel sera le Namespace dans lequel créer le proxy
  • /out:HelloWorldPROXY.cs : le nom du fichier à créer
Après exécution, on obtient un fichier de quelques kilo-octets, contenant la définition d'une classe nommée HelloWorldWS qui va nous permettre d'appeler les méthodes du WebService éponyme. 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 HelloServiceInc;

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 et étant résidant LOCAL ! L'appel de ses méthodes entraine un appel des méthodes du WebService (au format SOAP, par HTTP). Voici ce que cela donne dans notre exemple :

L'utilisation de la classe proxy


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

L'utilisation de la classe proxy


</COPIE>

retour à l'index

Partie 4 : Le mot de la fin

Conclusion

Voilà, vous avez eu votre premier contact avec les WebServices et leurs environnement. J'en profite pour rappeler que ce ne sont pas des technologies propriétaires Microsoft mais fortement soutenue par elle. Vous trouverez des informations sur les WebServices chez le World Wide Web Consortium (W3C), et aussi chez Microsoft (en ce qui concerne LEUR implémentation).

Vous n'avez vu ici que l'aspect "pratique" des WebServices, mais l'intégration des technologies sur lesquelles ils reposent (XML, SOAP, X-Path, XSD, DTD, ...) est très forte dans l'environnement .NET. Si vous désirez en savoir un peu plus, je vous conseille de parcourrir le cours sur XML et les WebServices ou encore celui sur ASP.NET & ADO.NET.

Ce qu'il faut retenir de ce "pseudo-comparatif" (il faut l'avouer ) est que RMI n'est pas universel alors que les WebServices le sont. Certes, il existe certainement des portages de RMI, mais ils ne deviennent alors universels que par là, alors que les WebServices sont universels par définition. Les technologies et protocoles utilisés sont publiques, bien définis, soutenu par de grandes puissances industrielles.
Pour RMI on utilise de la sérialisation binaire, et on gagne alors en vitesse. Les WebServices sont en retard ? Non, car eux aussi peuvent se passer de la sérialisation XML-SOAP et transférer par TCP en binaire. Mais alors, on est alors dans l'impasse de la non universalité. Toutefois, cette universalité n'est valable que selon la qualité des implémentations de ces technologies, de la conformité des implémentations et surtout de la qualité inhérente des technologies utilisées.

retour à l'index

Remerciements

Mesdames Anne-Marie DERRY-PINNA et Mireille BLAY-FORNARINO, professeurs à l'ESSI, pour leurs encouragements.
Monsieur Laurent ELLERBACH, responsable relation études supérieures chez Microsoft France, pour son soutien et ses idées.
Merci enfin à Romain VASSEUR pour ses remarques et corrections au cours de ses relectures.

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, très bien, 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 16-10-2002, dernière màj 28-10-2002


pages vues depuis le 14 oct. 2002