Como: adicionar programaticamente a capacidade de descoberta para um cliente e serviço do WCF

Este tópico mostra como tornar um serviço WCF (Windows Communication Foundation) detectável. Este exemplo é baseado no exemplo de auto-hospedagem.

Para configurar o exemplo de serviço de auto-hospedagem existente para Descoberta

  1. Abra a solução de auto-hospedagem no Visual Studio 2012. O exemplo está localizado no diretório TechnologySamples\Basic\Service\Hosting\SelfHost.

  2. Adicione uma referência a System.ServiceModel.Discovery.dll no projeto do serviço. Pode ser que você veja uma mensagem de erro dizendo “System. ServiceModel.Discovery.dll ou uma de suas dependências requer uma versão posterior do .NET Framework do que a especificada no projeto ..." Se você vir essa mensagem, clique com o botão direito do mouse no projeto no Gerenciador de Soluções e escolha Propriedades. Na janela Propriedades do Projeto, verifique se a Estrutura de Destino está como .NET Framework 4.6.1.

  3. Abra o arquivo Service.cs e adicione a seguinte instrução using:

    using System.ServiceModel.Discovery;
    
  4. No método Main(), dentro da instrução using, adicione uma instância ServiceDiscoveryBehavior ao host de serviço.

    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());
    
            // ...
        }
    }
    

    O ServiceDiscoveryBehavior especifica que o serviço ao qual ele é aplicado é detectável.

  5. Adicione um UdpDiscoveryEndpoint ao host de serviço logo após o código que adiciona o ServiceDiscoveryBehavior.

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

    Esse código especifica que as mensagens de descoberta devem ser enviadas para o ponto de extremidade de descoberta UDP padrão.

Para criar um aplicativo cliente que usa a descoberta para chamar o serviço

  1. Adicione um novo aplicativo de console chamado DiscoveryClientApp à solução.

  2. Adicionar uma referência a System.ServiceModel.dll e System.ServiceModel.Discovery.dll

  3. Copie os arquivos GeneratedClient.cs e App.config do projeto cliente existente para o novo projeto DiscoveryClientApp. Para fazer isso, clique com o botão direito do mouse nos arquivos no Gerenciador de Soluções, selecione Copiar e selecione o projeto DiscoveryClientApp; clique com o botão direito do mouse e selecione Colar.

  4. Abra Program.cs.

  5. Adicione as seguintes declarações de using.

    using System.ServiceModel;
    using System.ServiceModel.Discovery;
    using Microsoft.ServiceModel.Samples;
    
  6. Adicione um método estático chamado FindCalculatorServiceAddress() à classe Program.

    static EndpointAddress FindCalculatorServiceAddress()
    {
    }
    

    Esse método usa a descoberta para pesquisar o serviço CalculatorService.

  7. Dentro do método FindCalculatorServiceAddress, crie uma nova instância DiscoveryClient, passando um UdpDiscoveryEndpoint para o construtor.

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

    Isso informa ao WCF que a classe DiscoveryClient deve usar o ponto de extremidade de descoberta UDP padrão para enviar e receber mensagens de descoberta.

  8. Na linha seguinte, chame o método Find e especifique uma instância FindCriteria que contenha o contrato de serviço que você deseja pesquisar. Nesse caso, especifique ICalculator.

    // Find ICalculatorService endpoints
    FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
    
  9. Após a chamada a Find, verifique se há pelo menos um serviço correspondente e retorne o EndpointAddress do primeiro serviço correspondente. Caso contrário, retorne null.

    if (findResponse.Endpoints.Count > 0)
    {
        return findResponse.Endpoints[0].Address;
    }
    else
    {
        return null;
    }
    
  10. Adicione um método estático chamado InvokeCalculatorService à classe Program.

    static void InvokeCalculatorService(EndpointAddress endpointAddress)
    {
    }
    

    Esse método usa o endereço de ponto de extremidade retornado de FindCalculatorServiceAddress para chamar o serviço de calculadora.

  11. Dentro do método InvokeCalculatorService, crie uma instância da classe CalculatorServiceClient. Essa classe é definida pelo exemplo de auto-hospedagem. Ele foi gerado usando Svcutil.exe.

    // Create a client
    CalculatorClient client = new CalculatorClient();
    
  12. Na linha seguinte, defina o endereço do ponto de extremidade do cliente para o endereço do ponto de extremidade retornado de FindCalculatorServiceAddress().

    // Connect to the discovered service endpoint
    client.Endpoint.Address = endpointAddress;
    
  13. Imediatamente após o código da etapa anterior, chame os métodos expostos pelo serviço de calculadora.

    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. Adicione código ao método Main() na classe Program para chamar FindCalculatorServiceAddress.

    public static void Main()
    {
        EndpointAddress endpointAddress = FindCalculatorServiceAddress();
    }
    
  15. Na linha seguinte, chame InvokeCalculatorService() e passe o endereço do ponto de extremidade retornado de FindCalculatorServiceAddress().

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

Para testar o aplicativo

  1. Abra um prompt de comandos com privilégios elevados e execute Service.exe.

  2. Abra um prompt de comando e execute Discoveryclientapp.exe.

  3. A saída de service.exe deve ter a aparência da saída a seguir.

    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. A saída de Discoveryclientapp.exe deve ter a aparência da saída a seguir.

    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.
    

Exemplo

Veja a seguir uma listagem do código para este exemplo. Como esse código se baseia no exemplo de auto-hospedagem, somente os arquivos alterados são listados.

// 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();

        }
    }
}

Confira também