Procedura: aggiungere capacità di individuazione a un client e un servizio WCF a livello di codice
In questo argomento viene illustrato come rendere individuabile un servizio Windows Communication Foundation (WCF). È basato sull'esempio Servizio indipendente.
Per configurare l'esempio di servizio indipendente esistente per l'individuazione
Aprire la soluzione Self-Host in Visual Studio 2010. 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 il sistema ServiceModel.Discovery.dll o una delle relative dipendenze richiede una versione successiva di .NET Framework rispetto a quella specificata nel progetto. In questo caso fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Proprietà. Nella finestra Proprietà progetto verificare che Framework di destinazione sia impostato su .NET Framework versione 4.Aprire il file Service.cs e aggiungere l'istruzione
using
seguente.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 istruzioni
using
riportate di seguito.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 utilizzare 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 Servizio indipendente. È 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 eseguire il test dell'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 https://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
Premere <INVIO> per uscire.
Esempio
Di seguito è riportato un elenco del codice per questo esempio. Poiché questo codice è basato sull'esempio Servizio indipendente, vengono elencati solo i file modificati. Per ulteriori informazioni su esempio Servizio indipendente, vedere Istruzioni per l'impostazione.
// 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();
}
}
}