Partager via


Spécification d’une adresse de point de terminaison

Toutes les communications avec un service Windows Communication Foundation (WCF) se produisent via ses points de terminaison. Chacun ServiceEndpoint contient un Address, un Bindinget un Contract. Le contrat spécifie les opérations disponibles. La liaison spécifie comment communiquer avec le service, et l’adresse spécifie où trouver le service. Chaque point de terminaison doit avoir une adresse unique. L’adresse du point de terminaison est représentée par la EndpointAddress classe, qui contient un URI (Uniform Resource Identifier) qui représente l’adresse du service, un Identity, qui représente l’identité de sécurité du service et une collection de valeurs facultatives Headers. Les en-têtes facultatifs fournissent des informations d’adressage plus détaillées pour identifier ou interagir avec le point de terminaison. Par exemple, les en-têtes peuvent indiquer comment traiter un message entrant, où le point de terminaison doit envoyer un message de réponse ou quelle instance d’un service utiliser pour traiter un message entrant d’un utilisateur particulier lorsque plusieurs instances sont disponibles.

Définition d’une adresse de point de terminaison

Dans WCF, un EndpointAddress modélise une référence de point de terminaison (EPR) comme définie dans la norme WS-Addressing.

L’URI d’adresse de la plupart des transports comporte quatre parties. Par exemple, cet URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint comporte les quatre parties suivantes :

  • Schéma : http :

  • Machine : www.fabrikam.com

  • (Facultatif) Port : 322

  • Chemin d’accès : /mathservice.svc/secureEndpoint

Une partie du modèle EPR est que chaque référence de point de terminaison peut contenir certains paramètres de référence qui ajoutent des informations d’identification supplémentaires. Dans WCF, ces paramètres de référence sont modélisés en tant qu’instances de la AddressHeader classe.

L’adresse de point de terminaison d’un service peut être spécifiée de manière impérative à l’aide du code ou de manière déclarative par le biais de la configuration. La définition de points de terminaison dans le code n’est généralement pas pratique, car les liaisons et adresses d’un service déployé sont généralement différentes de celles utilisées pendant le développement du service. En règle générale, il est plus pratique de définir des points de terminaison de service à l’aide de la configuration plutôt que du code. La conservation des informations de liaison et d’adressage hors du code leur permet de changer sans avoir à recompiler et à redéployer l’application. Si aucun point de terminaison n’est spécifié dans le code ou dans la configuration, le runtime ajoute un point de terminaison par défaut sur chaque adresse de base pour chaque contrat implémenté par le service.

Il existe deux façons de spécifier des adresses de point de terminaison pour un service dans WCF. Vous pouvez spécifier une adresse absolue pour chaque point de terminaison associé au service ou fournir une adresse de base pour le ServiceHost service, puis spécifier une adresse pour chaque point de terminaison associé à ce service défini par rapport à cette adresse de base. Vous pouvez utiliser chacune de ces procédures pour spécifier les adresses de point de terminaison d’un service dans la configuration ou le code. Si vous ne spécifiez pas d’adresse relative, le service utilise l’adresse de base. Vous pouvez également avoir plusieurs adresses de base pour un service, mais chaque service n’est autorisé qu’une seule adresse de base pour chaque transport. Si vous avez plusieurs points de terminaison, chacun d’entre eux étant configuré avec une liaison différente, leurs adresses doivent être uniques. Les points de terminaison qui utilisent la même liaison mais des contrats différents peuvent utiliser la même adresse.

Lors de l’hébergement avec IIS, vous ne gérez pas l’instance ServiceHost vous-même. L’adresse de base est toujours l’adresse spécifiée dans le fichier .svc pour le service lors de l’hébergement dans IIS. Vous devez donc utiliser des adresses de point de terminaison relatives pour les points de terminaison hébergés par IIS. La fourniture d'une adresse de point de terminaison entièrement qualifiée peut entraîner des erreurs dans le déploiement du service. Pour plus d’informations, consultez Déploiement d’un service WCF hébergé dans Internet Information Services.

Définition d’adresses de point de terminaison dans la configuration

Pour définir un point de terminaison dans un fichier de configuration, utilisez l’élément <de point de terminaison> .

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello"/>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Lorsque la Open méthode est appelée (autrement dit, lorsque l’application d’hébergement tente de démarrer le service), le système recherche un <élément de service> avec un attribut de nom qui spécifie « UE. Samples.HelloService". Si l’élément <de service> est trouvé, le système charge la classe spécifiée et crée des points de terminaison à l’aide des définitions de point de terminaison fournies dans le fichier de configuration. Ce mécanisme vous permet de charger et de démarrer un service avec deux lignes de code tout en gardant les informations de liaison et d’adressage en dehors de votre code. L’avantage de cette approche est que ces modifications peuvent être apportées sans avoir à recompiler ou à redéployer l’application.

Les en-têtes facultatifs sont déclarés dans un élément <headers>. Voici un exemple des éléments utilisés pour spécifier des points de terminaison pour un service dans un fichier de configuration qui distingue entre deux en-têtes : les clients « Gold » de http://tempuri1.org/ et les clients « Standard » de http://tempuri2.org/. Le client appelant ce service doit avoir les en-têtes appropriés<> dans son fichier de configuration.

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri1.org/">Gold</Member>
          </headers>
        </endpoint>
        <endpoint address="/Address2"
          binding="basicHttpBinding" 
          contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri2.org/">Silver</Member>
          </headers>
        </endpoint>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Les en-têtes peuvent également être définis sur des messages individuels au lieu de tous les messages sur un point de terminaison (comme indiqué précédemment). Cela se fait en utilisant OperationContextScope pour créer un nouveau contexte dans une application cliente afin d'ajouter un en-tête personnalisé au message sortant, comme illustré dans l'exemple suivant.

SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
  using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
  {
    MessageHeader header
      = MessageHeader.CreateHeader(
      "Service-Bound-CustomHeader",
      "http://Microsoft.WCF.Documentation",
      "Custom Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // Making calls.
    Console.WriteLine("Enter the greeting to send: ");
    string greeting = Console.ReadLine();

    //Console.ReadLine();
    header = MessageHeader.CreateHeader(
        "Service-Bound-OneWayHeader",
        "http://Microsoft.WCF.Documentation",
        "Different Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // One-way
    wcfClient.Push(greeting);
    this.wait.WaitOne();

    // Done with service.
    wcfClient.Close();
    Console.WriteLine("Done!");
    Console.ReadLine();
  }
}
catch (TimeoutException timeProblem)
{
  Console.WriteLine("The service operation timed out. " + timeProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
  Console.WriteLine("There was a communication problem. " + commProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
    Using scope As New OperationContextScope(wcfClient.InnerChannel)
        Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
                            "http://Microsoft.WCF.Documentation", "Custom Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' Making calls.
        Console.WriteLine("Enter the greeting to send: ")
        Dim greeting As String = Console.ReadLine()

        'Console.ReadLine();
        header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
                                            "http://Microsoft.WCF.Documentation", "Different Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' One-way
        wcfClient.Push(greeting)
        Me.wait.WaitOne()

        ' Done with service. 
        wcfClient.Close()
        Console.WriteLine("Done!")
        Console.ReadLine()
    End Using
Catch timeProblem As TimeoutException
    Console.WriteLine("The service operation timed out. " & timeProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
Catch commProblem As CommunicationException
    Console.WriteLine("There was a communication problem. " & commProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
End Try

Adresse du point de terminaison dans les métadonnées

Une adresse de point de terminaison est représentée dans le Web Services Description Language (WSDL) en tant qu'élément WS-Addressing EndpointReference (EPR) à l'intérieur de l'élément du point de terminaison wsdl:port correspondant. L’EPR contient l’adresse du point de terminaison ainsi que toutes les propriétés d’adresse. Notez que l’EPR à l’intérieur wsdl:port remplace soap:Address comme indiqué dans l’exemple suivant.

Définition d’adresses de point de terminaison dans le code

Une adresse de point de terminaison peut être créée dans le code avec la EndpointAddress classe. L’URI spécifié pour l’adresse de point de terminaison peut être un chemin d’accès complet ou un chemin d’accès relatif à l’adresse de base du service. Le code suivant montre comment créer une instance de la EndpointAddress classe et l’ajouter à l’instance ServiceHost qui héberge le service.

L’exemple suivant montre comment spécifier l’adresse de point de terminaison complète dans le code.

Uri baseAddress = new Uri("http://localhost:8000/HelloService");
string address = "http://localhost:8000/HelloService/MyService";

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

L’exemple suivant montre comment ajouter une adresse relative (« MyService ») à l’adresse de base de l’hôte de service.

Uri baseAddress = new Uri("http://localhost:8000/HelloService");

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

Remarque

Les propriétés de l’application de service ServiceDescription ne doivent pas être modifiées après que la méthode OnOpening a été exécutée sur ServiceHostBase. Certains membres, tels que la propriété Credentials et les méthodes AddServiceEndpoint sur ServiceHostBase et ServiceHost, lèvent une exception si elles sont modifiées après ce point. D’autres vous permettent de les modifier, mais le résultat n’est pas défini.

De même, les valeurs ServiceEndpoint sur le client ne doivent pas être modifiées après l'appel à OnOpening sur le ChannelFactory. La Credentials propriété lève une exception si elle est modifiée après ce point. Les autres valeurs de description du client peuvent être modifiées sans erreur, mais le résultat n’est pas défini.

Que ce soit pour le service ou le client, il est recommandé de modifier la description avant d’appeler Open.

Utilisation de points de terminaison par défaut

Si aucun point de terminaison n’est spécifié dans le code ou dans la configuration, le runtime fournit des points de terminaison par défaut en ajoutant un point de terminaison par défaut sur chaque adresse de base pour chaque contrat de service implémenté par le service. L’adresse de base peut être spécifiée dans le code ou dans la configuration, et les points de terminaison par défaut sont ajoutés lorsqu’ils Open sont appelés sur le ServiceHost.

Si les points de terminaison sont explicitement fournis, les points de terminaison par défaut peuvent toujours être ajoutés en appelant AddDefaultEndpoints le ServiceHost serveur avant d’appeler Open. Pour plus d’informations sur les points de terminaison, les liaisons et les comportements par défaut, consultez Configuration simplifiée et Configuration simplifiée pour les services WCF.

Voir aussi