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
Abra a solução de auto-hospedagem no Visual Studio 2012. O exemplo está localizado no diretório TechnologySamples\Basic\Service\Hosting\SelfHost.
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.Abra o arquivo Service.cs e adicione a diretiva
using
a seguir.using System.ServiceModel.Discovery;
No método
Main()
, dentro da instruçãousing
, 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.
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
Adicione um novo aplicativo de console chamado
DiscoveryClientApp
à solução.Adicionar uma referência a
System.ServiceModel.dll
eSystem.ServiceModel.Discovery.dll
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.
Abra Program.cs.
Adicione as diretivas
using
a seguir.using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
Adicione um método estático chamado
FindCalculatorServiceAddress()
à classeProgram
.static EndpointAddress FindCalculatorServiceAddress() { }
Esse método usa a descoberta para pesquisar o serviço
CalculatorService
.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.
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)));
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; }
Adicione um método estático chamado
InvokeCalculatorService
à classeProgram
.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.Dentro do método
InvokeCalculatorService
, crie uma instância da classeCalculatorServiceClient
. Essa classe é definida pelo exemplo de auto-hospedagem. Ele foi gerado usando Svcutil.exe.// Create a client CalculatorClient client = new CalculatorClient();
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;
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();
Adicione código ao método
Main()
na classeProgram
para chamarFindCalculatorServiceAddress
.public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
Na linha seguinte, chame
InvokeCalculatorService()
e passe o endereço do ponto de extremidade retornado deFindCalculatorServiceAddress()
.if (endpointAddress != null) { InvokeCalculatorService(endpointAddress); } Console.WriteLine("Press <ENTER> to exit."); Console.ReadLine();
Para testar o aplicativo
Abra um prompt de comandos com privilégios elevados e execute Service.exe.
Abra um prompt de comando e execute Discoveryclientapp.exe.
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
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();
}
}
}