Procédure : ajouter par programmation la détectabilité à un service et un client WCF

Cette rubrique explique comment rendre un service Windows Communication Foundation (WCF) détectable. Elle est basée sur l’exemple Self-Host.

Pour configurer l'exemple existant de service Self-Host pour la découverte

  1. Ouvrez la solution Self-Host dans Visual Studio 2012. L'exemple se trouve dans le répertoire TechnologySamples\Basic\Service\Hosting\SelfHost.

  2. Ajoutez au projet du service une référence à System.ServiceModel.Discovery.dll. Un message d'erreur s'affiche éventuellement, indiquant « System. ServiceModel.Discovery.dll ou l'une de ses dépendances requiert une version ultérieure de .NET Framework à celle spécifiée dans le projet... ». Si ce message s'affiche, cliquez avec le bouton droit sur le projet dans l'Explorateur de solutions et choisissez Propriétés. Dans la fenêtre Propriétés du projet, vérifiez que le Framework cible est .NET Framework 4.6.1.

  3. Ouvrez le fichier Service.cs et ajoutez l'instruction using suivante.

    using System.ServiceModel.Discovery;
    
  4. Dans la méthode Main(), à l'intérieur de l'instruction using, ajoutez une instance ServiceDiscoveryBehavior à l'hôte du service.

    public static void Main()
    {
        // Create a ServiceHost for the CalculatorService type.
        using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
        {
            // Add a ServiceDiscoveryBehavior
            serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
    
            // ...
        }
    }
    

    L'instance ServiceDiscoveryBehavior spécifie que le service auquel elle s'applique est détectable.

  5. Ajoutez un objet UdpDiscoveryEndpoint à l'hôte du service, juste après le code qui ajoute l'instance ServiceDiscoveryBehavior.

    // Add ServiceDiscoveryBehavior
    serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
    
    // Add a UdpDiscoveryEndpoint
    serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
    

    Ce code spécifie que les messages de découverte doivent être envoyés au point de terminaison de découverte UDP standard.

Pour créer une application cliente utilisant la découverte pour appeler le service

  1. Ajoutez à la solution une nouvelle application console nommée DiscoveryClientApp.

  2. Ajoutez une référence à System.ServiceModel.dll et à System.ServiceModel.Discovery.dll.

  3. Copiez les fichiers GeneratedClient.cs et App.config du projet client existant dans le nouveau projet DiscoveryClientApp. Pour ce faire, cliquez avec le bouton droit sur les fichiers dans l’Explorateur de solutions, sélectionnez Copier, puis sélectionnez le projet DiscoveryClientApp, cliquez avec le bouton droit et sélectionnez Coller.

  4. Ouvrez le fichier Program.cs.

  5. Ajoutez les instructions using suivantes.

    using System.ServiceModel;
    using System.ServiceModel.Discovery;
    using Microsoft.ServiceModel.Samples;
    
  6. Ajoutez une méthode statique nommée FindCalculatorServiceAddress() à la classe Program.

    static EndpointAddress FindCalculatorServiceAddress()
    {
    }
    

    Cette méthode utilise la découverte pour rechercher le service CalculatorService.

  7. À l'intérieur de la méthode FindCalculatorServiceAddress, créez une instance DiscoveryClient, en transmettant un objet UdpDiscoveryEndpoint au constructeur.

    static EndpointAddress FindCalculatorServiceAddress()
    {
        // Create DiscoveryClient
        DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
    }
    

    Cela indique à WCF que la classe DiscoveryClient doit utiliser le point de terminaison de découverte UDP standard pour envoyer et recevoir des messages de découverte.

  8. Sur la ligne suivante, appelez la méthode Find et spécifiez une instance FindCriteria qui contient le contrat de service que vous souhaitez rechercher. Le contrat à spécifier dans le cas présent est ICalculator.

    // Find ICalculatorService endpoints
    FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
    
  9. Après l'appel à la méthode Find, vérifiez s'il existe au moins un service correspondant et retournez l'objet EndpointAddress du premier service correspondant. Autrement, retournez une valeur null.

    if (findResponse.Endpoints.Count > 0)
    {
        return findResponse.Endpoints[0].Address;
    }
    else
    {
        return null;
    }
    
  10. Ajoutez une méthode statique nommée InvokeCalculatorService à la classe Program.

    static void InvokeCalculatorService(EndpointAddress endpointAddress)
    {
    }
    

    Cette méthode utilise l'adresse du point de terminaison retournée par l'objet FindCalculatorServiceAddress pour appeler le service de calculatrice.

  11. À l'intérieur de la méthode InvokeCalculatorService, créez une instance de la classe CalculatorServiceClient. Cette classe est définie par l’exemple Self-Host. Elle a été générée à l'aide de Svcutil.exe.

    // Create a client
    CalculatorClient client = new CalculatorClient();
    
  12. Sur la ligne suivante, définissez l'adresse du point de terminaison du client sur l'adresse du point de terminaison retournée par l'objet FindCalculatorServiceAddress().

    // Connect to the discovered service endpoint
    client.Endpoint.Address = endpointAddress;
    
  13. Immédiatement après le code de l'étape précédente, appelez les méthodes exposées par le service de calculatrice.

    Console.WriteLine("Invoking CalculatorService at {0}", endpointAddress);
    
    double value1 = 100.00D;
    double value2 = 15.99D;
    
    // Call the Add service operation.
    double result = client.Add(value1, value2);
    Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
    
    // Call the Subtract service operation.
    result = client.Subtract(value1, value2);
    Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
    
    // Call the Multiply service operation.
    result = client.Multiply(value1, value2);
    Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
    
    // Call the Divide service operation.
    result = client.Divide(value1, value2);
    Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
    Console.WriteLine();
    
    //Closing the client gracefully closes the connection and cleans up resources
    client.Close();
    
  14. Ajoutez un code à la méthode Main() dans la classe Program pour appeler FindCalculatorServiceAddress.

    public static void Main()
    {
        EndpointAddress endpointAddress = FindCalculatorServiceAddress();
    }
    
  15. Sur la ligne suivante, appelez InvokeCalculatorService() et passez l'adresse du point de terminaison retournée par FindCalculatorServiceAddress().

    if (endpointAddress != null)
    {
        InvokeCalculatorService(endpointAddress);
    }
    
    Console.WriteLine("Press <ENTER> to exit.");
    Console.ReadLine();
    

Pour tester l'application

  1. Ouvrez une invite de commandes avec élévation de privilèges et exécutez Service.exe.

  2. Ouvrez une invite de commandes et exécutez Discoveryclientapp.exe.

  3. La sortie de service.exe doit ressembler à la sortie suivante.

    Received Add(100,15.99)
    Return: 115.99
    Received Subtract(100,15.99)
    Return: 84.01
    Received Multiply(100,15.99)
    Return: 1599
    Received Divide(100,15.99)
    Return: 6.25390869293308
    
  4. La sortie de Discoveryclientapp.exe doit ressembler à la sortie suivante.

    Invoking CalculatorService at http://localhost:8000/ServiceModelSamples/service
    Add(100,15.99) = 115.99
    Subtract(100,15.99) = 84.01
    Multiply(100,15.99) = 1599
    Divide(100,15.99) = 6.25390869293308
    
    Press <ENTER> to exit.
    

Exemple

L'intégralité du code utilisé dans cet exemple est présentée ci-dessous. Comme ce code est basé sur l’exemple Self-Host, seuls les fichiers modifiés sont répertoriés.

// Service.cs
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Discovery;

namespace Microsoft.ServiceModel.Samples
{
    // See SelfHost sample for service contract and implementation
    // ...

        // Host the service within this EXE console application.
        public static void Main()
        {
            // Create a ServiceHost for the CalculatorService type.
            using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
            {
                // Add the ServiceDiscoveryBehavior to make the service discoverable
                serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
                serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());

                // Open the ServiceHost to create listeners and 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.WriteLine();
                Console.ReadLine();
            }
        }
    }
}
// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Discovery;
using Microsoft.ServiceModel.Samples;
using System.Text;

namespace DiscoveryClientApp
{
    class Program
    {
        static EndpointAddress FindCalculatorServiceAddress()
        {
            // Create DiscoveryClient
            DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());

            // Find ICalculatorService endpoints
            FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));

            if (findResponse.Endpoints.Count > 0)
            {
                return findResponse.Endpoints[0].Address;
            }
            else
            {
                return null;
            }
        }

        static void InvokeCalculatorService(EndpointAddress endpointAddress)
        {
            // Create a client
            CalculatorClient client = new CalculatorClient();

            // Connect to the discovered service endpoint
            client.Endpoint.Address = endpointAddress;

            Console.WriteLine("Invoking CalculatorService at {0}", endpointAddress);

            double value1 = 100.00D;
            double value2 = 15.99D;

            // Call the Add service operation.
            double result = client.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

            // Call the Subtract service operation.
            result = client.Subtract(value1, value2);
            Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);

            // Call the Multiply service operation.
            result = client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

            // Call the Divide service operation.
            result = client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
            Console.WriteLine();

            //Closing the client gracefully closes the connection and cleans up resources
            client.Close();
        }
        static void Main(string[] args)
        {
            EndpointAddress endpointAddress = FindCalculatorServiceAddress();

            if (endpointAddress != null)
            {
                InvokeCalculatorService(endpointAddress);
            }

            Console.WriteLine("Press <ENTER> to exit.");
            Console.ReadLine();

        }
    }
}

Voir aussi