Como: Adicionar programaticamente a capacidade de descoberta a um serviço WCF e cliente
Este tópico explica como tornar um serviço WCF (Windows Communication Foundation) detetável. Baseia-se no exemplo Self-Host .
Para configurar o exemplo de serviço Self-Host existente para Descoberta
Abra a solução Self-Host no Visual Studio 2012. O exemplo está localizado no diretório TechnologySamples\Basic\Service\Hosting\SelfHost.
Adicione uma referência ao
System.ServiceModel.Discovery.dll
projeto de serviço. Poderá ver uma mensagem de erro a dizer "Sistema. 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, certifique-se de que o Target Framework é .NET Framework 4.6.1.Abra o arquivo Service.cs e adicione a seguinte
using
diretiva.using System.ServiceModel.Discovery;
Main()
No método, dentro dausing
instrução, adicione uma ServiceDiscoveryBehavior instância 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 é detetá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 à solução chamada
DiscoveryClientApp
.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, em seguida, selecione o projeto DiscoveryClientApp, clique com o botão direito do mouse e selecione Colar.
Abra o Program.cs.
Aditar as seguintes
using
diretivas.using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
Adicione um método estático chamado
FindCalculatorServiceAddress()
àProgram
classe.static EndpointAddress FindCalculatorServiceAddress() { }
Este método utiliza a deteção para procurar o
CalculatorService
serviço.Dentro do
FindCalculatorServiceAddress
método, crie uma nova DiscoveryClient instância, passando em a UdpDiscoveryEndpoint para o construtor.static EndpointAddress FindCalculatorServiceAddress() { // Create DiscoveryClient DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); }
Isso informa ao WCF que a DiscoveryClient classe deve usar o ponto de extremidade de descoberta UDP padrão para enviar e receber mensagens de descoberta.
Na próxima linha, chame o Find método e especifique uma FindCriteria instância 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 para 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 nomeado
InvokeCalculatorService
àProgram
classe.static void InvokeCalculatorService(EndpointAddress endpointAddress) { }
Esse método usa o endereço do ponto de extremidade retornado para chamar o serviço de
FindCalculatorServiceAddress
calculadora.Dentro do
InvokeCalculatorService
método, crie uma instância daCalculatorServiceClient
classe. Essa classe é definida pelo exemplo Self-Host . Foi gerado usando Svcutil.exe.// Create a client CalculatorClient client = new CalculatorClient();
Na próxima linha, defina o endereço do ponto de extremidade do cliente como o endereço do ponto de extremidade retornado do
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
Main()
ao método naProgram
classe para chamarFindCalculatorServiceAddress
.public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
Na próxima linha, chame o
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 a aplicação
Abra um prompt de comando elevado e execute Service.exe.
Abra um prompt de comando e execute Discoveryclientapp.exe.
A saída do service.exe deve ser semelhante à 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 do Discoveryclientapp.exe deve ser semelhante à 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
A seguir está uma lista do código para este exemplo. Como esse código é baseado no exemplo Self-Host , somente os arquivos que são 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();
}
}
}