RSS

WCF avec C#

07 Juin

Windows Communication Foundation (WCF) est la nouvelle couche de communication du framework 3.0. Cette couche a été créée afin d’unifier les différents modèles d’écritures d’applications "communicantes".

Les Application distribuées

Une application distribuée est une application dont tous les éléments qui la composent (classes, persistance, logique métier) sont distants géographiquement et communiquent entre eux via des réseaux locaux d’entreprise ou par Internet en utilisant le protocole IP.

Les composants des applications distribuées sont réutilisables et servent souvent à plus d’une application simultanément. Cependant, l’utilisateur final n’a pas conscience de la nature distribuée de l’applicatif car il utilise une interface – Web ou Windows Forms –, dont le but souvent est de fédérer tous les éléments distants pour atteindre l’objectif de l’application tout en masquant tous les mécanismes d’accès.

Le principe même des applications distribuées n’est pas nouveau. Beaucoup de technologies et de protocoles, souvent incompatibles entre eux ont été mis en œuvre pour permettre aux composants d’une application distribuée, de communiquer entre eux. Parmi ces technologies, on peut citer :

    • COM (Component Object Model) : technologie de communication inter application propre à l’environnement Windows. Cette technologie ne permet pas de construire à proprement parler des applications distribuées mais sert d’interface pour faire communiquer des applications sur une même machine. (les différents logiciels de la suite bureautique Microsoft Office par exemple).
    • DCOM (Distributed Component Object Model) : version Distribuée de COM.
    • .Net Remoting : technologie de communication inter application incluse dans le Framework .Net 2.0, basée sur un modèle client/serveur permettant la communication et la transmission d’objets entre les applications.
    • RMI : équivalent Java du .Net Remoting
    • Services Web : technologie permettant de faire communiquer des composants entre eux, indépendamment de la plateforme sur laquelle ils sont hébergés, en utilisant un protocole de communication et un format de fichier unique et standardisé basé sur du XML. Contrairement aux technologies évoquées précédemment, grâce à la nature standardisée des échanges, il devient tout à fait possible de faire communiquer des modules hébergés sous Windows avec d’autres hébergés sous Linux ou Unix. C’est cette interopérabilité associée à une relative facilité de mise en œuvre, qui fait que les services web sont aujourd’hui une des technologies les plus utilisées, pour construire des applications distribuées.

Windows Communication Foundation (WCF)

Windows Communication Foundation (WCF) est la nouvelle couche de communication du framework 3.0. Cette couche a été créée afin d’unifier les différents modèles d’écritures d’applications "communicantes".

WCF, ou Windows Communication Foundation, est une des nouveautés majeures de la version 3.0 du Framework .Net. WCF fournit un modèle de programmation unifiée pour construire des applications distribuées, WCF va nous permettre de faire communiquer des composants applicatifs se trouvant sur une même machine, mais le plus souvent sur différentes machines reliées en réseau.

La plupart des fonctionnalités de WCF sont incluses dans l’assembly System.ServiceModel.dll et accessibles depuis le namespace System.ServiceModel.

Dans WCF, tous les services exposent des contrats. Les contrats étant le moyen standard pour décrire ce que fait le service. WCF définit 4 types de contrats:

  • Contrat de services: Décrit les opérations que le client peut effectuer via le service.
  • Contrat de données: Définit de quels types sont les données qui sont passées depuis et vers le service. WCF définit des contrats implicites pour les types primitifs.
  • Contrat d’erreurs: Précise les erreurs qui sont soulevées par le service et la façon dont le service gère les erreurs et les propage à ses clients.
  • Contrat de message: Les contrats de message peuvent être dactylographiés ou non typé et sont utiles pour interopérer avec des services qui utilisent des formats propriétaires de message.

SOA : Services Oriented Architecture

Selon l’OASIS (Organisation for Avancement of Structured Information Standards), l’organisation pour la promotion des standards de l’information structurée, « l’architecture orientée service (SOA : Services Oriented Architecture) est un paradigme d’organisation des ressources distribuées, potentiellement contrôlées par des domaines différents. ».

Malgré le fait que des technologies comme DCOM, RMI ou .Net Remoting permettent de transporter les objets et donc de dépasser les frontières de la machine grâce au réseau, on s’est souvent heurté à des problèmes de compatibilité entre plateformes, d’où le besoin d’une standardisation et la mise en commun des protocoles (SOAP, XML, .). De là est née la notion d’architecture orientée services (SOA).

Le principe même de SOA repose sur les 4 principes suivants :

  • La définition du service est explicite : Un service est une classe exposée à travers les réseaux. Le but de ce service est de fournir une prestation bien définie (exemple : fournir la date et l’heure dans un pays donné). Les détails d’un service (la manière dont il doit être appelé, les paramètres à spécifier.) sont contenus dans un document standardisé, qui fait office de contrat entre le client et le serveur.
  • Les services sont autonomes : Un service se doit d’être totalement autonome On doit pouvoir le remplacer ou le déplacer sans que cela affecte d’autres services. Un service implémente ses propres composants et ses propres méthodes d’accès aux données, il ne doit dépendre d’aucun élément externe.
  • Les clients et les services ne partagent que des contrats : On a vu dans le premier principe du SOA, que les services exposent des contrats pour exposer aux clients leurs fonctionnalités et comment les utiliser. Cette interface est la seule chose que le serveur partage avec le client. Comme en programmation orientée objet, le client n’a pas à connaitre comment procède le service pour arriver à ses fins. En aucun cas, le service et le client ne doivent partager du code.
  • La compatibilité est basée sur les règles.

-1-Les applications consomment des services distants, pouvant réaliser des tâches métiers techniques, en s’échangeant des messages (-3-).
-2-Chaque service possède un contrat qui fournit des spécifications techniques sur les opérations qu’il propose (signature, données à fournir entrée, données retourne.).
-4-et-5-Chaque contrat possède un schéma, qui décrit des messages échangées entre les services et les applications qui les consomment.

A la vue de la diversité des technologies d’applications distribuées et surtout de leur nature propriétaire, qui fait que non seulement la plupart sont incompatibles entre elles mais qu’en plus, chacune étant différente, il est souvent nécessaire pour un développeur d’en connaitre plusieurs, Microsoft a développé Windows Communication Foundation.

WCF en C#.

Fonctionnement de la communication entre applications

Afin que les applications puissent communiquer il faut qu’un certain nombre de contraintes soient respectées.

  • Définir les méthodes exposées par le serveur
  • Définir les types de données transmissibles entre applications
  • Définir l’ABC de la communication

Définir les méthodes exposées par le serveur

Pour que le client puisse appeler des méthodes sur le serveur encore faut-il que ce premier connaisse les méthodes disponibles sur le serveur. WCF est très strict sur la façon d’implémenter la communication entre applications.

En effet les méthodes exposées par WCF doivent toutes être définies dans une interface "décorée" par l’attribut ServiceContract. De plus les fonctions que l’on veut exposer par WCF doivent être "décorées" par l’attribut OperationContract.

Cette interface définie donc une méthode qu’un client peut appeler à distance. Au passage vous remarquerez que nous passons un paramètre sans aucun problème. Cette interface définit donc le contrat de notre service. En effet les types primaires tel que string, int, float, etc peuvent être utilisés sans aucun problème ni modification. Mais comment permettre à des types personnalisés d’être transmit par WCF d’un serveur à un client ?

Définir les types de données transmissibles entre applications

Afin de marquer une classe comme transmissible par WCF il suffit d’utiliser l’attribut [DataContract]. Cet attribut est défini dans l’assembly System.Runtime.Serialization qu’il faut donc ajouter à son projet. Ce choix d’implémentation est très intéressant car il permet de ne pas bousculer toute la modélisation d’un projet en obligeant l’héritage par une classe comme MarshalByRefObject en Remoting. Cela vous permet donc de migrer facilement et avec peu de modifications un projet qui n’as pas été initialement prévu pour fonctionner en WCF.

Une fois que votre classe est "décorée" avec l’attribut [DataContract] il faut ensuite identifier les méthodes que nous allons exposer aux futurs clients de notre application.

EndPoint (Point de terminaison) Définir l’ABC de la communication

C’est sous cet acronyme que Microsoft définit les 3 étapes essentielles du déploiement d’un service WCF.

  • A pour Address : Définit l’adresse du serveur qui expose le service
  • B pour Binding : Définit la façon dont le service sera exposé
  • C pour Contract : Définit le contrat que le service remplit

La grande force de WCF est sans aucun doute la façon dont il a été pensé. En effet tout ce qui touche au déploiement et à la consommation d’un service WCF est défini dans le fichier de configuration de l’application. Cela permet de s’affranchir entièrement des contraintes de déploiement au moment du développement. En unifiant ainsi les différentes façons de programmer une application distribuée, WCF permet une souplesse et une facilité d’utilisation extrêmement agréable.

Définir l’adresse du service

Afin de pouvoir exposer un service vous devez définir l’adresse à partir de laquelle il sera accessible. Pour cela il faut définir les sections correspondantes dans le fichier de configuration de l’application. Ces sections doivent toutes se trouver dans <system.serviceModel> de votre fichier de configuration.

L’attribut address vous permet de définir un point de terminaison c’est à dire une URI où le service sera accessible.

De plus cela vous permet de configurer la totalité de l’abc de la communication.

Définir le binding du service

Le binding est la façon dont le service sera exposé. C’est à dire qu’il vous permet de définir le protocole utilisé pour transporter vos objets sur le réseaux ou en local. Chaque binding à ses avantages et ses inconvénients mais au niveau du développeur ce choix ne doit pas être bloquant. En effet lors de votre développement vous ne savez pas toujours dans quel environnement votre application va être déployée. L’administrateur réseau ne veut peut être pas ouvrir un port sur un serveur pour des raisons de sécurité, ou alors il voudrait pouvoir définir quel port. De même il préfère peut être vu la topologie de son réseau que les communications se fassent en tcp afin de réduire la charge réseau. Toutes ces questions ne sont donc pas à la charge du développeur mais bien de l’administrateur réseaux qui va s’occuper de l’installation de votre application. C’est la que l’on comprend une autre des choses merveilleuses de WCF. En .NET Remoting ce choix était fait par l’équipe de développement et l’administrateur réseaux n’avait aucun moyen d’influer dessus. WCF de part l’uniformisation des techniques d’utilisation des protocoles permet de rendre ce choix à la personne concernée : l’administrateur réseaux.

Le binding est donc défini par l’attribut "binding" de notre fichier de configuration.

WCF supporte plusieurs bindings :

Bindings WCF

Binding

Description

Transport

Codage

Inter?

Basic binding

Ce binding est dédié aux clients et services basés sur ASMX,ou qui respectent le profil WS-I Basic Profile 1.1.

HTTP/HTTPS

Texte, MTOM

Oui

TCP binding

Binding sécurisée et fiable, optimisé pour les communications WCF-to-WCF.

TCP

Binaire

Non

IPC binding

Offre des fonctionnalités équivalentes à NetTcpBinding à ceci près qu’il est limité à la communication inter-processus (donc sur la même machine). C’est le plus performant.

IPC

Binaire

Non

Web Service (WS) binding

Ce binding est conçu pour interopérer avec tout framework prennant en charge la spécification WS-* (sessions fiables, transactions distribuées et sécurité).

HTTP/HTTPS

Texte, MTOM

Oui

Dual WS binding

Similaire au WSHttpBinding, de plus, il supporte les contrats de service duplex qui permettent aux services et clients d’envoyer et recevoir des messages.

HTTP

Texte, MTOM

Non

MSMQ binding

Ce binding est dédié aux communications avec file d’attente.

MSMQ

Binaire

Non

Définir le contrat de service

Le "contract" (contrat en français) est tout simplement la liste des méthodes appellables par les clients. Rapellez vous, nous avons défini une interface que nous avons décoré avec les attributs [ServiceContract] et [OperationContract].

C’est cette interface que nous allons définir en tant que contrat pour notre client.

A noter qu’un contrat est obligatoirement une interface. Vous ne pouvez pas définir une classe en tant que contrat car le framework vous impose une séparation forte entre ce que les clients peuvent voir et ce que le serveur implémente.

Ceci est une bonne chose qui vous permettra à la longue de ne pas vous mélanger entre des classes qui sont appelable par le client, des classes qui ne le sont pas et des interfaces de définition de services.

Hébergement du service

Chaque service WCF doit être hébergé dans un processus Windows appelé processus hôte. Un unique processus hôte peut héberger plusieurs services et le même service peut être hébergé dans de multiples processus hôtes. WCF supporte les processus hôtes suivants:

  • Internet Information Services (IIS) 5/6 : Limités aux services transportés via HTTP(S).
  • Self-hosting (Auto-hébergement) : Dans ce cas, le processus hôte est une application Windows Forms, une application console, ou un service NT. Ce mode d’hébergement supporte tous les types de transport pris en charge par WCF.
  • Internet Information Services (IIS) 7 : Il supporte tous les types de transport pris en charge par WCF.

// TODO: Traduction en français

– Services can be hosted or executed, so that it will be available to everyone accessing from the client. WCF service can be hosted by following mechanism

  • IIS : Internet information Service provides number of advantages if a Service uses Http as protocol. It does not require Host code to activate the service, it automatically activates service code.
  • Windows Activation Service : (WAS) is the new process activation mechanism that ships with IIS 7.0. In addition to HTTP based communication, WCF can also use WAS to provide message-based activation over other protocols, such as TCP and named pipes.
  • Self-Hosting : WCF service can be self hosted as console application, Win Forms or WPF application with graphical UI.
  • Windows Service : WCF can also be hosted as a Windows Service, so that it is under control of the Service Control Manager (SCM).

Architecture de WCF

Maquettes

Voici une maquette, avec : un Web Service, un service WCF et un WCF RIA Service.

Hébergement

Dans IIS.

Ajout projet Web : « WebServerServices »

Cas du Web Service XML

Côté serveur

Fichier : WebServiceCalculator.asmx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace WebServerServices
{
    /// <summary>
    /// Description résumée de WebServiceCalculator
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // Pour autoriser l'appel de ce service Web depuis un script à l'aide d'ASP.NET AJAX, supprimez les marques de commentaire de la ligne suivante. 
    // [System.Web.Script.Services.ScriptService]
    public class WebServiceCalculator : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }
        [WebMethod]
        public double Add(double op1, double op2)
        {
            return op1 + op2;
        }
        [WebMethod]
        public double Substract(double op1, double op2)
        {
            return op1 - op2;
        }
        [WebMethod]
        public double Multiply(double op1, double op2)
        {
            return op1 * op2;
        }
        [WebMethod]
        public double Divide(double op1, double op2)
        {
            return op1 / op2;
        }

        [WebMethod]
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        [WebMethod]
        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

Tests du Web Service

Récupération des métadonnées

Clients

  • Windows Form

 

//TODO

 

  • WPF

 

//TODO

 

  • Silverlight

Ajout de la référence : WebServiceCalculator sur le client.

L’ajout de la référence créé automatiquement un proxy sur le

client (CalculatorWebServiceReference.WebServiceCalculatorSoapClient)

Ainsi qu’un fichier de configuration ServiceReferences.ClientConfig.

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="WebServiceCalculatorSoap" maxBufferSize="2147483647"
            maxReceivedMessageSize="2147483647">
          <security mode="None" />
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:88/WebServerServices/WebServiceCalculator.asmx"
          binding="basicHttpBinding" bindingConfiguration="WebServiceCalculatorSoap"
          contract="CalculatorWebServiceReference.WebServiceCalculatorSoap"
          name="WebServiceCalculatorSoap" />
    </client>
  </system.serviceModel>
</configuration>

Création d’une instance CalcWebService de WebServiceCalculatorSoapClient.

        CalculatorWebServiceReference.WebServiceCalculatorSoapClient CalcWebService;

        public PageWebService()
        {
            InitializeComponent();
            CalcWebService = new CalculatorWebServiceReference.WebServiceCalculatorSoapClient();
            CalcWebService.AddCompleted += new EventHandler<CalculatorWebServiceReference.AddCompletedEventArgs>(CalcWebService_AddCompleted);
        }

        void CalcWebService_AddCompleted(object sender, CalculatorWebServiceReference.AddCompletedEventArgs e)
        {
            LabelResult.Content = string.Format("Op1 + Op2 = {0}", e.Result);
        }

Exécution du client Silverlight consommant le Web Service

Cas du service WCF

Côté serveur

Ajout item Service WCF : « WcfServiceCalculator»

  <system.serviceModel>   
   <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

.NET Framework 4 simplifie la configuration d’un service WCF en supprimant la nécessité d’avoir un élément < service>. Si vous n’ajoutez pas de points de terminaison dans la section < service> éventuelle, et si votre service ne définit aucun point de terminaison par programme, un jeu de points de terminaison est automatiquement ajouté à votre service : un pour chaque adresse de base de service et pour chaque contrat implémenté par votre service. Dans chacun de ces points de terminaison, l’adresse du point de terminaison correspond à l’adresse de base, la liaison est déterminée par le schéma d’adresse de base et le contrat est celui implémenté par votre service. Si vous n’avez pas besoin de spécifier de comportements de point de terminaison ou de service, ni de modifier un paramètre de liaison, il est inutile de spécifier un fichier de configuration. Si un service implémente deux contrats et que l’hôte active à la fois les transports HTTP et TCP, l’hôte de service crée quatre points de terminaison par défaut, un pour chaque contrat utilisant chaque transport. Pour créer des points de terminaison par défaut, l’hôte de service doit savoir quelles liaisons utiliser. Ces paramètres sont spécifiés dans une section < protocolMappings> à l’intérieur de la section < system.serviceModel>. La section < protocolMappings> contient une liste de schémas de protocole de transport mappés aux types de liaison. L’hôte du service utilise les adresses de base qui lui sont transmises pour déterminer quelle liaison utiliser. L’exemple suivant utilise l’élément < protocolMappings>.

Définition du contrat :

Dans « IWcfServiceCalculator.cs »

namespace WebServerServices
{
    // REMARQUE : vous pouvez utiliser la commande Renommer du menu Refactoriser pour changer le nom d'interface "IWcfServiceCalculator" à la fois dans le code et le fichier de configuration.
    [ServiceContract(Namespace = "")]
    public interface IWcfServiceCalculator
    {
        [OperationContract]
        double Add(double op1, double op2);

        [OperationContract]
        double Substract(double op1, double op2);

        [OperationContract]
        double Multiply(double op1, double op2);

        [OperationContract]
        double Divide(double op1, double op2);

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

    }

    // Utilisez un contrat de données comme indiqué dans l'exemple ci-après pour ajouter les types composites aux opérations de service.
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

}


Implémentation du contrat:

Dans “WcfServiceCalculator.svc.cs

namespace WebServerServices
{
    public class WcfServiceCalculator : IWcfServiceCalculator
    {
        public double Add(double op1, double op2)
        {
            return op1 + op2;
        }

        public double Substract(double op1, double op2)
        {
            return op1 - op2;
        }

        public double Multiply(double op1, double op2)
        {
            return op1 * op2;
        }

        public double Divide(double op1, double op2)
        {
            return op1 / op2;
        }

        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }

    }
}

Tests du Service WCF

Récupération des métadonnées

Clients

  • Windows Form
//TODO
  • WPF
//TODO
  • Silverlight

Ajout de la référence : WcfServiceCalculator sur le client.

Modification automatique du fichier de configuration ServiceReferences.ClientConfig.

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IWcfServiceCalculator" maxBufferSize="2147483647"
            maxReceivedMessageSize="2147483647">
          <security mode="None" />
        </binding>
        <binding name="WebServiceCalculatorSoap" maxBufferSize="2147483647"
            maxReceivedMessageSize="2147483647">
          <security mode="None" />
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:88/WebServerServices/WebServiceCalculator.asmx"
          binding="basicHttpBinding" bindingConfiguration="WebServiceCalculatorSoap"
          contract="CalculatorWebServiceReference.WebServiceCalculatorSoap"
          name="WebServiceCalculatorSoap" />
      <endpoint address="http://localhost:88/WebServerServices/WcfServiceCalculator.svc"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IWcfServiceCalculator"
          contract="CalculatorWCFServiceReference.IWcfServiceCalculator"
          name="BasicHttpBinding_IWcfServiceCalculator" />
    </client>
  </system.serviceModel>
</configuration>

Cas du WCF RIA Service

Côté serveur

Ajout item Domain Service Class : « DomainServiceCalculator»

« Enable client access » pour la génération automatique du proxy.

Déclaration automatique du « httpModule » dans le fichier Web.Config

 <system.web>
    <httpModules>
      <add name="DomainServiceModule" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpModules>
...
 </system.web>

Tests du Service WCF RIA

http://localhost:88/WebServerServices/WebServerServices-DomainServiceCalculator.svc

Clients

  • Windows Form
  • WPF
  • Silverlight

On lie le client Silverlight au service RIA hébergé par le serveur Web.

Modification automatique du fichier de configuration Web.Config

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      multipleSiteBindingsEnabled="true" />
    
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
  </system.serviceModel>

Génération automatique du code du proxy sur le client Silverlight.

        /// <summary>
        /// Initializes a new instance of the <see cref="DomainServiceCalculator"/> class.
        /// </summary>
        public DomainServiceCalculator() : 
                this(new WebDomainClient<IDomainServiceCalculatorContract>(new Uri("WebServerServices-DomainServiceCalculator.svc", UriKind.Relative)))
        {
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="DomainServiceCalculator"/> class with the specified service URI.
        /// </summary>
        /// <param name="serviceUri">The DomainServiceCalculator service URI.</param>
        public DomainServiceCalculator(Uri serviceUri) : 
                this(new WebDomainClient<IDomainServiceCalculatorContract>(serviceUri))
        {
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="DomainServiceCalculator"/> class with the specified <paramref name="domainClient"/>.
        /// </summary>
        /// <param name="domainClient">The DomainClient instance to use for this domain context.</param>
        public DomainServiceCalculator(DomainClient domainClient) : 
                base(domainClient)
        {
            this.OnCreated();
        }

Modification automatique du fichier de configuration Web.Config

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      multipleSiteBindingsEnabled="true" />

ASP.NET Compatibility

Activer le mode de compatibilité ASP.NET dans Windows Communication Foundation (WCF). Les services qui s’exécutent dans le mode de compatibilité ASP.NET participent pleinement au pipeline de l’application ASP.NET et peuvent utiliser des fonctionnalités ASP.NET telles que l’autorisation de fichier/d’URL, l’état de session et la classe HttpContext. La classe HttpContext permet l’accès aux cookies, aux sessions ainsi qu’à d’autres fonctionnalités ASP.NET. Dans ce mode, les liaisons doivent utiliser le transport HTTP et le service lui-même doit être hébergé dans les services IIS.

Le service conserve l’état de chaque client (à l’aide de la fonctionnalité correspondante) tandis que plusieurs opérations de service sont appelées pour effectuer un calcul. Le client peut récupérer le résultat actuel en appelant Result et remettre le résultat à zéro en appelant Clear.

Le service utilise la session ASP.NET pour stocker le résultat de chaque session de client. Cela lui permet de conserver le résultat d’exécution de chaque client tandis qu’il reçoit plusieurs appels. Le service dépend étroitement de l’état de session ASP.NET et nécessite que le mode de compatibilité ASP.NET fonctionne correctement. Ces spécifications sont définies de manière déclarative en appliquant l’attribut AspNetCompatibilityRequirements.

Impossible d’utiliser le service WCF précédant.

using System.ServiceModel.Activation;

namespace WebServerServices
{
    // REMARQUE : vous pouvez utiliser la commande Renommer du menu Refactoriser pour changer le nom de classe "WcfServiceCalculator" à la fois dans le code, le fichier svc et le fichier de configuration.
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
    public class WcfServiceCalculator : IWcfServiceCalculator
    {
        public double Add(double op1, double op2)
        {
            return op1 + op2;
        }


Client ASP.NET

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebServerServices
{
    public partial class WebFormClient : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            WebServiceCalculator cs = new WebServiceCalculator();
            double n1 = Convert.ToDouble(TextBox1.Text);
            double n2 = Convert.ToDouble(TextBox2.Text);

            double result = cs.Add(n1, n2);
            Label1.Text = string.Format("egal = {0}", result);


        }

        protected void Button2_Click(object sender, EventArgs e)
        {
            WcfServiceCalculator cs = new WcfServiceCalculator();
            double n1 = Convert.ToDouble(TextBox1.Text);
            double n2 = Convert.ToDouble(TextBox2.Text);

            double result = cs.Add(n1, n2);
            Label2.Text = string.Format("egal = {0}", result);


        }

        protected void Button3_Click(object sender, EventArgs e)
        {
            DomainServiceCalculator cs = new DomainServiceCalculator();
            double n1 = Convert.ToDouble(TextBox1.Text);
            double n2 = Convert.ToDouble(TextBox2.Text);

            double result = cs.Add(n1, n2);
            Label3.Text = string.Format("egal = {0}", result);


        }
    }
}

Fiddler2 (Pour IE<9)

Modification des URLs.

Sur le client, dans le fichier : « ServiceReferences.ClientConfig »,

  • changer « localhost » en « localhost. ».

Configurer la référence des services :

  • CalculatorWCFServiceReference
  • CalculatorWebServiceReference

En changeant : « localhost » en « localhost. ».

Utiliser l’URL : « http://localhost.:88/WebServerServices/SilverlightApplicationClientTestPage.aspx »

Cas du Web Service

Cas du service WCF

Cas de WCF RIA Services

Autres types d’hébergement

Service auto-hébergé dans une application managée de type Console

Les scénarios courants autorisés par l’auto-hébergement sont les services WCF qui s’exécutent à l’intérieur d’applications console. L’hébergement d’un service WCF à l’intérieur d’une application console est en général utile pendant la phase de développement du service. Cela simplifie le débogage, l’obtention d’informations de suivi, la détermination de ce qui se passe à l’intérieur de l’application et leur déplacement en les copiant vers de nouveaux emplacements.

Pour héberger un service à l’intérieur d’une application managée, incorporez le code du service à l’intérieur du code de l’application managée, définissez un point de terminaison pour le service soit de manière impérative dans le code, soit de façon déclarative par le biais de la configuration ou à l’aide des points de terminaison par défaut, puis créez une instance de ServiceHost.

Ajouter un projet Application Console ConsoleServerServices.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ServiceModel;

namespace ConsoleServerServices
{
    class Program
    {
        // Host the service within this EXE console application.
        static void Main(string[] args)
        {
            using (ServiceHost serviceHost = new ServiceHost(typeof(WcfServiceCalculator)))
            {
                try
                {
                    // Open the ServiceHost to start listening for messages.
                    serviceHost.Open();

                    // The service can now be accessed.
                    Console.WriteLine("The service is ready.");
                    Console.WriteLine("Press <ENTER> to terminate service.");
                    Console.ReadLine();

                    // Close the ServiceHost.
                    serviceHost.Close();
                }
                catch (TimeoutException timeProblem)
                {
                    Console.WriteLine(timeProblem.Message);
                    Console.ReadLine();
                }
                catch (CommunicationException commProblem)
                {
                    Console.WriteLine(commProblem.Message);
                    Console.ReadLine();
                }
            }
        }
    }
}

Librairie de classe CalculatorInterface pour le contrat IWcfServiceCalculator.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

using System.Runtime.Serialization;


namespace CalculatorInterface
{
    // REMARQUE : vous pouvez utiliser la commande Renommer du menu Refactoriser pour changer le nom d'interface "IWcfServiceCalculator" à la fois dans le code et le fichier de configuration.
    [ServiceContract(Namespace = "")]
    public interface IWcfServiceCalculator
    {
        [OperationContract]
        double Add(double op1, double op2);

        [OperationContract]
        double Substract(double op1, double op2);

        [OperationContract]
        double Multiply(double op1, double op2);

        [OperationContract]
        double Divide(double op1, double op2);

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

    }

    // Utilisez un contrat de données comme indiqué dans l'exemple ci-après pour ajouter les types composites aux opérations de service.
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

}

Ajouter au projet ConsoleServerServices une référence sur CalculatorInterface.

image

Ajouter au projet ConsoleServerServices un item Service Windows WcfServiceCalculator.svc.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

using System.ServiceModel.Activation;
using CalculatorInterface;

namespace ConsoleServerServices
{
    // REMARQUE : vous pouvez utiliser la commande Renommer du menu Refactoriser pour changer le nom de classe "WcfServiceCalculator" à la fois dans le code, le fichier svc et le fichier de configuration.
    public class WcfServiceCalculator : CalculatorInterface.IWcfServiceCalculator
    {
        public double Add(double op1, double op2)
        {
            return op1 + op2;
        }

        public double Substract(double op1, double op2)
        {
            return op1 - op2;
        }

        public double Multiply(double op1, double op2)
        {
            return op1 * op2;
        }

        public double Divide(double op1, double op2)
        {
            return op1 / op2;
        }

        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }

    }
}

Client WindowsForm

Ajouter au projet une référence sur CalculatorInterface.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CalculatorInterface;
using System.ServiceModel;

namespace WindowsFormsClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonGDUDCIIS_Click(object sender, EventArgs e)
        {
            ServiceReferenceWCF.WcfServiceCalculatorClient service = new ServiceReferenceWCF.WcfServiceCalculatorClient();
            ServiceReferenceWCF.CompositeType ct = new ServiceReferenceWCF.CompositeType();
            ct.BoolValue = true;
            ct.StringValue = textBox1.Text;
            label1.Text = "";
            label1.Text = service.GetDataUsingDataContract(ct).StringValue;
        }

        private void buttonGDUDCConsole_Click(object sender, EventArgs e)
        {
            using (ChannelFactory<CalculatorInterface.IWcfServiceCalculator> customersFactory =
                new ChannelFactory<CalculatorInterface.IWcfServiceCalculator>("ConsoleServerBasicHttpBinding_IWcfServiceCalculator"))
            {
                CalculatorInterface.IWcfServiceCalculator serviceProxy = customersFactory.CreateChannel();
                CalculatorInterface.CompositeType ct = new CalculatorInterface.CompositeType();
                ct.BoolValue = true;
                ct.StringValue = textBox1.Text;
                label1.Text = "";
                label1.Text = serviceProxy.GetDataUsingDataContract(ct).StringValue;
            }
        }
    }
}

Hébergement dans un service Windows managé

//TODO

Publicités
 
Poster un commentaire

Publié par le 7 juin 2011 dans Développement

 

Étiquettes : ,

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 :