Procedura: aggiungere capacità di individuazione a un client e un servizio WCF a livello di codice
Questo argomento illustra come rendere individuabile un servizio Windows Communication Foundation (WCF). Si basa sull'esempio di self-host.
Per configurare l'esempio di servizio indipendente esistente per l'individuazione
Aprire la soluzione Self-Host in Visual Studio 2012. L'esempio si trova nella directory TechnologySamples\Basic\Service\Hosting\SelfHost.
Aggiungere al progetto di servizio un riferimento a
System.ServiceModel.Discovery.dll
. Potrebbe essere visualizzato un messaggio di errore a indicare che "System. ServiceModel.Discovery.dll o una delle relative dipendenze richiede una versione successiva di .NET Framework rispetto a quella specificata nel progetto…" Se viene visualizzato questo messaggio, fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Proprietà. Nella finestra Proprietà progetto verificare che il framework di destinazione sia .NET Framework 4.6.1.Aprire il file Service.cs e aggiungere la direttiva seguente
using
.using System.ServiceModel.Discovery;
Nel metodo
Main()
, all'interno dell'istruzioneusing
, aggiungere un'istanza ServiceDiscoveryBehavior all'host del servizio.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()); // ... } }
ServiceDiscoveryBehavior specifica che il servizio a cui è applicato è individuabile.
Aggiungere UdpDiscoveryEndpoint all'host del servizio subito dopo il codice che aggiunge ServiceDiscoveryBehavior.
// Add ServiceDiscoveryBehavior serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); // Add a UdpDiscoveryEndpoint serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Questo codice specifica che i messaggi di individuazione devono essere inviati all'endpoint di individuazione UDP standard.
Per creare un'applicazione client che utilizza l'individuazione per chiamare il servizio
Aggiungere alla soluzione una nuova applicazione console denominata
DiscoveryClientApp
.Aggiungere un riferimento a
System.ServiceModel.dll
eSystem.ServiceModel.Discovery.dll
Copiare i file GeneratedClient.cs e App.config dal progetto client esistente al nuovo progetto DiscoveryClientApp. A tale scopo fare clic con il pulsante destro del mouse sui file in Esplora soluzioni, scegliere Copia, quindi fare clic sul progetto DiscoveryClientApp, fare clic con il pulsante destro del mouse e scegliere Incolla.
Aprire Program.cs.
Aggiungere le direttive seguenti
using
.using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
Aggiungere un metodo statico denominato
FindCalculatorServiceAddress()
alla classeProgram
.static EndpointAddress FindCalculatorServiceAddress() { }
Questo metodo utilizza l'individuazione per cercare il servizio
CalculatorService
.Creare nel metodo
FindCalculatorServiceAddress
una nuova istanza DiscoveryClient, passando un elemento UdpDiscoveryEndpoint al costruttore.static EndpointAddress FindCalculatorServiceAddress() { // Create DiscoveryClient DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); }
In questo modo WCF viene informato del fatto che la classe DiscoveryClient deve usare l'endpoint di individuazione UDP standard per inviare e ricevere messaggi di individuazione.
Alla riga successiva, chiamare il metodo Find e specificare un'istanza FindCriteria che contiene il contratto di servizio che si desiderare cercare. In questo caso specificare
ICalculator
.// Find ICalculatorService endpoints FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
Successivamente alla chiamata a Find, verificare se sia disponibile almeno un servizio corrispondente e restituire l'elemento EndpointAddress del primo servizio corrispondente. In caso contrario, restituire
null
.if (findResponse.Endpoints.Count > 0) { return findResponse.Endpoints[0].Address; } else { return null; }
Aggiungere un metodo statico denominato
InvokeCalculatorService
alla classeProgram
.static void InvokeCalculatorService(EndpointAddress endpointAddress) { }
Questo metodo utilizza l'indirizzo endpoint restituito da
FindCalculatorServiceAddress
per chiamare il servizio di calcolo.Creare all'interno del metodo
InvokeCalculatorService
un'istanza della classeCalculatorServiceClient
. Questa classe viene definita dall'esempio Self-Host. È stata generata utilizzando Svcutil.exe.// Create a client CalculatorClient client = new CalculatorClient();
Alla riga successiva impostare l'indirizzo endpoint del client sull'indirizzo endpoint restituito da
FindCalculatorServiceAddress()
.// Connect to the discovered service endpoint client.Endpoint.Address = endpointAddress;
Immediatamente dopo il codice per il passaggio precedente, chiamare i metodi esposti dal servizio di calcolo.
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();
Aggiungere codice al metodo
Main()
nella classeProgram
per chiamareFindCalculatorServiceAddress
.public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
Alla riga successiva chiamare
InvokeCalculatorService()
e passare l'indirizzo endpoint restituito daFindCalculatorServiceAddress()
.if (endpointAddress != null) { InvokeCalculatorService(endpointAddress); } Console.WriteLine("Press <ENTER> to exit."); Console.ReadLine();
Per testare l'applicazione
Aprire un prompt dei comandi con privilegi elevati ed eseguire Service.exe.
Aprire un prompt dei comandi ed eseguire Discoveryclientapp.exe.
L'output di service.exe deve essere analogo all'output indicato di seguito.
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
L'output di Discoveryclientapp.exe deve essere analogo all'output indicato di seguito.
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.
Esempio
Di seguito è riportato un elenco del codice per questo esempio. Poiché questo codice è basato sull'esempio Self-Host, vengono elencati solo i file modificati.
// 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();
}
}
}