Procedimiento para agregar detectabilidad mediante programación a un cliente y un servicio de WCF
En este tema se explica cómo hacer que un servicio Windows Communication Foundation (WCF) sea detectable. Está basado en el ejemplo de hospedaje automático.
Para configurar el ejemplo de servicio de host automático existente repara para la detección
Abra la solución de hospedaje automático en Visual Studio 2012. El ejemplo se encuentra en el directorio TechnologySamples\Basic\Service\Hosting\SelfHost.
Agregue una referencia a
System.ServiceModel.Discovery.dll
al proyecto de servicio. Puede ver un mensaje de error que diga "System. "ServiceModel.Discovery.dll o una de sus dependencias necesita una versión posterior de .NET Framework a la que se especifica en el proyecto...". Si ve este mensaje, haga clic con el botón derecho en el Explorador de soluciones y seleccione Propiedades. En la ventana Propiedades del proyecto, asegúrese de que la Plataforma de destino es .NET Framework 4.6.1.Abra el archivo Service.cs y agregue la siguiente directiva
using
.using System.ServiceModel.Discovery;
En el método
Main()
, dentro de la instrucciónusing
, agregue una instancia ServiceDiscoveryBehavior al host de servicio.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()); // ... } }
La clase ServiceDiscoveryBehavior especifica que el servicio al que se aplica es reconocible.
Agregue UdpDiscoveryEndpoint al host de servicio justo después del código que agrega ServiceDiscoveryBehavior.
// Add ServiceDiscoveryBehavior serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); // Add a UdpDiscoveryEndpoint serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Este código especifica que los mensajes de detección se deberían enviar al extremo de detección de UDP estándar.
Para crear una aplicación cliente que usa la detección para llamar al servicio
Agregue a la solución una aplicación de consola nueva denominada
DiscoveryClientApp
.Agregue una referencia a
System.ServiceModel.dll
ySystem.ServiceModel.Discovery.dll
.Copie los archivos GeneratedClient.cs y App.config del proyecto de cliente existente en el nuevo proyecto DiscoveryClientApp. Para ello, haga clic con el botón derecho en los archivos del Explorador de soluciones, seleccione Copiar y, a continuación, seleccione el proyecto DiscoveryClientApp, haga clic con el botón derecho y seleccione Pegar.
Abra Program.cs.
Añade las siguientes directivas
using
.using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
Agregue un método estático llamado
FindCalculatorServiceAddress()
a la claseProgram
.static EndpointAddress FindCalculatorServiceAddress() { }
Este método usa la detección para buscar el servicio
CalculatorService
.Dentro del método
FindCalculatorServiceAddress
, cree una instancia DiscoveryClient nueva, pasando UdpDiscoveryEndpoint al constructor.static EndpointAddress FindCalculatorServiceAddress() { // Create DiscoveryClient DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); }
Esto indica a WCF que la clase DiscoveryClient debe usar el punto de conexión de detección de UDP estándar para enviar y recibir mensajes de detección.
En la línea siguiente, llame al método Find y especifique una instancia FindCriteria que contenga el contrato de servicios que desea buscar. En este caso, especifique
ICalculator
.// Find ICalculatorService endpoints FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
Después de la llamada a Find, compruebe si hay por lo menos un servicio coincidente y devuelva la clase EndpointAddress del primer servicio coincidente. De lo contrario, devuelva
null
.if (findResponse.Endpoints.Count > 0) { return findResponse.Endpoints[0].Address; } else { return null; }
Agregue un método estático llamado
InvokeCalculatorService
a la claseProgram
.static void InvokeCalculatorService(EndpointAddress endpointAddress) { }
Este método utiliza la dirección del extremo devuelta de
FindCalculatorServiceAddress
para llamar al servicio de calculadora.Dentro del método
InvokeCalculatorService
, cree una instancia de la claseCalculatorServiceClient
. Esta clase se define mediante el ejemplo de hospedaje automático. Se ha generado mediante Svcutil.exe.// Create a client CalculatorClient client = new CalculatorClient();
En la línea siguiente, establezca la dirección del extremo del cliente en la dirección del extremo devuelta de
FindCalculatorServiceAddress()
.// Connect to the discovered service endpoint client.Endpoint.Address = endpointAddress;
Inmediatamente después del código del paso anterior, llame a los métodos expuestos por el servicio 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();
Agregue el código al método
Main()
de la claseProgram
para llamar aFindCalculatorServiceAddress
.public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
En la línea siguiente, llame a
InvokeCalculatorService()
y pase la dirección del extremo devuelta deFindCalculatorServiceAddress()
.if (endpointAddress != null) { InvokeCalculatorService(endpointAddress); } Console.WriteLine("Press <ENTER> to exit."); Console.ReadLine();
Para probar la aplicación
Abra un símbolo del sistema elevado y ejecute Service.exe.
Abra un símbolo del sistema y ejecute Discoveryclientapp.exe.
El resultado de service.exe debería ser el siguiente.
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
El resultado de Discoveryclientapp.exe debería ser el siguiente.
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.
Ejemplo
A continuación, se muestra una lista completa del código de este ejemplo. Dado que este código se basa en el ejemplo de hospedaje automático, solo se enumeran los archivos que cambian.
// 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();
}
}
}