Accueil > .Net, ASP.Net, C#, Internet, WCF > [C#] Les Web Services

[C#] Les Web Services

Dans ce billet un peu long (c’est pour ça que je fais une intro), on va voir un peu ce qui se fait dans le domaine des Web Services.

Enfin, surtout un bref aperçu donnant les bases pour les créer et les consommer. Et ce, que ce soit du asmx ou du WCF.

Bonne lecture !


Qu’est ce qu’un Web service ?

Un Web Service (ou service web, comme on veut, que j’abrégerais en WS) est un programme permettant un échange de données entre différents systèmes, dans des environnements  pouvant être de nature différente (Windows – Unix, par exemple).

Un WS est, par essence, exposé (visible, accessible) sur internet ou en intranet, par des applications diverses.

Depuis longtemps, le W3C a émit diverses recommandations au sujet des WS. Ces recommandations tournent autour du protocole SOAP ainsi que du WSDL, le tout étant destiné aux architectures de type SOA.

Quelques très brèves définitions pour poser les choses :

SOAP (ancien acronyme de Simple Object Access Protocol, voir wikipédia pour plus d’infos) est un protocole d’échange basé sur du XML. Il est constitué d’une enveloppe contenant un header et un body.

Le header est constitué des diverses informations comme la date, le statut http…

Exemple de header d'une requête SOAP (obtenu via SoapUI)

Le body, lui, contient les données échangées, au format XML.

Le WSDL (Web Services Description Language) est un gros XML décrivant le service pour qui veut l’utiliser. C’est grâce au WSDL que l’on pourra créer des clients.

L’architecture SOA (Service Oriented Architecture) est, comme son nom l’indique, un modèle permettant les interactions entre différents systèmes.

Comment créer un Web Service (asmx) ?

En C#, les premiers WS étaient au format asmx (l’extension des fichiers).

Pour créer un WS, on va créer un fichier de type « Web Service » dans une application web, du nom de « WebServiceDemo ».

On obtient deux fichiers :

  • WebServiceDemo.cs : code behind dans lequel on code réellement le service.
  • WebServiceDemo.asmx : façade qui fait référence au fichier de code behind.

Cependant, il est tout à fait possible de se passer du code behind et de faire pointer le asmx vers une autre classe, mais celle-ci devra impérativement hériter de System.Web.Services.WebService (et décorée des attributs qui vont bien, voir ensuite).

Dans ce cas là, on mettra, dans le asmx:

<%@ WebService Language="C#" Class="<namespace>.<classe>" %>

La classe est décorée de deux attributs : WebService et WebServiceBinding.

En général, on touche avant tout à l’attribut WebService, pour les paramètres suivants :
<ul>
<li>Namespace : par défaut http://tempuri.org/, il est quand même recommandé d’en utiliser un spécifique, surtout sur Internet.</li>
<li>Description : c’est pour afficher un petit texte descriptif dans la page générée automatiquement.</li>
</ul>
Maintenant, allons voir la méthode, dite « Web Method », du nom de l’attribut qui doit la décorer pour être visible sur le WS.

Là aussi, l’attribut prend en charge plusieurs paramètres. La MSDN sera plus détaillée sur ce point.

Quoiqu’il en soit, on a d’ors et déjà une méthode exposée en WS.

Pour la tester, rien de plus simple il suffit d’afficher la page.

Une Web Method peut prendre des paramètres.

Par contre, les paramètres ne peuvent avoir des valeurs par défaut comme ceci :

        [WebMethod]
        public string HelloWorld(string name = "Kerrubin")
        {
            return String.Format("Hello {0}", name);
        }

Le service fera comme si le paramètre par défaut n’existait pas.

De même, le WS ne prends pas en charge les surcharges, cela donne une exception à l’exécution :

Both System.String HelloWorld(System.String, System.String) and System.String HelloWorld(System.String) use the message name ‘HelloWorld’.  Use the MessageName property of the WebMethod custom attribute to specify unique message names for the methods.

Petite astuce au passage.

Si l’on veut envoyer un XML, on ne peut pas le faire sous forme de string.

En effet, les balises seront alors encodée et on se retrouvera avec des &lt; et &gt; un peu partout…

Dans ce cas, on peut renvoyer un XmlDocument.

Coté client, on aura alors pour retour un XmlNode et en utilisant XmlNode.OuterXml, on aura le flux XML complet :

        // Service
        [WebMethod]
        public XmlDocument MaWebMethod()
        {
            return MaMethodDeGenerationDeXmlDocument();
        }
        // Client
        MonService proxy = new MonService();
        XmlNode node = proxy.MaWebMethod();
        string xml = node.OuterXml;
        //On peut aussi reconstituer un DataSet en utilisant une méthode du type :
        protected static DataSet CreateDataSet(XmlNode node)
        {
            DataSet ds = new DataSet();
            using (MemoryStream stream = new MemoryStream())
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(node.OuterXml);
                xmlDoc.Save(stream);
                stream.Position = 0;
                ds.ReadXml(stream);
            }
            return ds;
        }

Comment créer un Web Service (WCF) ?
WCF (Windows Communication Foundation) est arrivé avec le Framework 3.0, c’est donc « relativement » récent (en termes de vie en entreprise, j’entends).

Pour rappel, le Framework 3.0 est sortit en novembre 2006, ce n’est ni plus ni moins qu’une surcouche du Framework 2.0 (sortit en novembre 2005).

Ainsi, tout ce qui fonctionne en 2.0 va fonctionner en 3.0 (et en 3.5 aussi, sortit en novembre 2007).

Et pour info, le Framework 4.0 est sortit en décembre 2010, au cas où certains seraient pas encore au courant…

La principale différence entre asmx et WCF, c’est que WCF se pose avant tout en plate-forme  de communication au sein d’une architecture SOA.

Ce qui veut dire que l’on peut utiliser WCF pour faire du Web Service, mais qu’on peut également l’utiliser en HTTP/HTTPS (Web Service simple ou en REST, compatible JSON), en TCP, en WCF-to-WCF (échange binaire) ou en MSMQ.

Autrement dit, WCF ne permet pas QUE de faire du Web Service.

Ensuite, WCF se base sur des contrats. Ce qui veut dire que l’on utilise une interface pour déclarer ce qui va être échangé et via quel moyen, de façon totalement décolérée avec le comment (implémentation).

On a donc une interface décorée de l’attribut System.ServiceModel.ServiceContract (on peut spécifier son namespace, entre autre) ainsi que des méthodes déclarée avec l’attribut System.ServiceModel.OperationContract.

D’un autre coté, on a des objets dont les propriétés devant être sérialisées (et donc envoyée à travers WCF) devront être décorée de l’attribut System.Runtime.Serialization.DataMember.

Et entre les deux, on a une classe qui implémente l’interface et utilise les objets.

C’est vraiment enfantin, exemple :

    // Entité
    [DataContract(Namespace = "http://www.kerrubin.com/Test/2011/05", Name = "Entity")]
    public class Entity
    {
        // Propriété qui sera sérialisée en 1er dans le XML, en ayant le nom LabelValue
        [DataMember(Order = 1, Name = "LabelValue")]
        public String ValueOne { get; set; }

        // Propriété qui sera sérialisée en 2nd dans le XML, en ayant le nom Value2
        [DataMember(Order = 2, Name = "Value2")]
        public String ValueTwo { get; set; }

        // Propriété qui ne sera pas sérialisée
        public String Property { get; set; }
    }

    // Interface / Contrat
    [ServiceContract(Namespace = "http://www.kerrubin.com/Test/2011/05", Name = "TestService")]
    public interface ITestService
    {
        [OperationContract]
        Entity GetEntity(string label);
    }

    // Implementation
    public class TestService : ITestService
    {
        public Entity GetEntity(string label)
        {
            return new Entity()
            {
                ValueOne = label,
                ValueTwo = "two"
            };
        }
    }

Pour l’heberger, on va créer un fichier TestService.svc, avec le code suivant :

<%@ ServiceHost Language="C#" Service="<namespace>.<classe>" %>

Après, c’est du web.config :

  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webHttp">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="Kr.Demo.WebService.TestServiceBehavior"><!-- Nom donné arbitrairement -->
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
      <service behaviorConfiguration="Kr.Demo.WebService.TestServiceBehavior"
               name="Kr.Demo.WebService.Business.TestService"> <!-- Namespace + classe implémentant le service -->
        <endpoint address="xml" behaviorConfiguration="webHttp" binding="webHttpBinding"
                  contract="Kr.Demo.WebService.Contracts.ITestService" />
        <endpoint address="" binding="wsHttpBinding" contract="Kr.Demo.WebService.Contracts.ITestService"/> <!-- Namespace + interface décrivant le service -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:3594/TestService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>

Et là, on a notre page de test qui est visible.

Pour en savoir plus, il y a des guides sur la MSDN.

Je reviendrais d’ici peu (je pense) pour faire une démo de REST.

Comment créer un client pour le Web Service ?
Une fois que l’on a le WS de prêt, on doit l’héberger quelque part, pour avoir la page de test et surtout l’URL vers le WSDL.

Après, on doit lancer l’invite de commande de VS et taper une commande du type :

wsdl /language:cs /out<chemin vers le proxy><nom de la classe>.cs http://<URL du service>?WSDL

Cette commande va générer automatiquement un proxy permettant d’appeler le WS.

Par contre, il est à noter que l’URL sera directement insérée dans le constructeur du proxy.

A nous de modifier le proxy en fonction des besoins (par exemple faire un constructeur prenant en paramètre l’URL).

Cependant, il est quand même déconseillé de trop modifier le proxy, à moins de vraiement savoir ce que l’on fait (ou pour des tests, comme il est simple de le reconstruire…).

Pour l’utilisation, rien de plus simple, il se comportera comme une classe de base, une fois instanciée.

Conclusion
Dans ce long billet, on a vu les bases des Web Service.

Si les Web Services sont surtout utilisés pour que des systèmes puissent communiquer entre eux et ce, en ne connaissant que le format d’échange, ce qui fait qu’il existe donc une forte interopérabilité.

Autrement dit, grâce à eux, il est possible de réaliser des applications centralisées ayant une  responsabilité partielle (SSO…).

Pour moi, le plus bel exemple est la gestion d’Amazon (wikipédia).

Cependant, il ne faut pas oublier que les données forcément par des canaux de communication. Ainsi, il faut quand même surveiller la taille des flux et les limiter le plus possible. Un bon exemple est de limiter le nombre de caractères des balises XML, sur un volume important de données, ça peut changer radicalement les choses (exemple : <LibelleFrancais></LibelleFrancais> fait 35 caractères. Sur 100.000 lignes, cela fera 350.000 caractères, soit 3,5Mo [approximation], <LibFr></LibFr> fera 1,5Mo).

Catégories :.Net, ASP.Net, C#, Internet, WCF
  1. Maroh
    10/05/2011 à 19:31

    Ah classe, je suis bien content de voir cet article, après avoir fait mon projet en asp en mvc (la lose) j’me disais que faire du web services s’y prêterait mieux et voilà, tu me ponds un super article🙂 merci

  2. 08/04/2015 à 22:53

    Tres bonne remarque a la fin de conseiller de limiter la taille des balises😉

  3. 10/05/2011 à 19:46

    Et je viens même de poster la suite : WebService – REST ^^

  1. 10/05/2011 à 19:45
  2. 17/01/2012 à 19:51
  3. 31/12/2012 à 16:04
  4. 02/01/2014 à 10:01
  5. 02/01/2015 à 20:00

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :