Vorgehensweise: Programmgesteuertes Hinzufügen der Ermittelbarkeit zu einem WCF-Dienst und -Client
In diesem Thema wird erläutert, wie Sie einen WCF-Dienst (Windows Communication Foundation) auffindbar machen. Grundlage hierfür ist das Beispiel für selbst gehostete Dienste.
So konfigurieren Sie das vorhandene Beispiel unter "Selbst gehostete Dienste" für die Suche
Öffnen Sie die Projektmappe für selbst gehostete Dienste in Visual Studio 2012. Das Beispiel befindet sich im Verzeichnis "TechnologySamples\Basic\Service\Hosting\SelfHost".
Fügen Sie dem Dienstprojekt einen Verweis auf
System.ServiceModel.Discovery.dll
hinzu. Möglicherweise wird folgende Fehlermeldung angezeigt: „System. ServiceModel.Discovery.dll“ oder eine der Abhängigkeiten erfordert eine spätere Version von .NET Framework als im Projekt angegeben…“. Falls diese Meldung angezeigt wird, klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Eigenschaften aus. Stellen Sie im Fenster Projekteigenschaften sicher, dass .NET Framework 4.6.1 als Zielframework angegeben ist.Öffnen Sie die Datei „Service.cs“, und fügen Sie die folgende
using
-Anweisung hinzu.using System.ServiceModel.Discovery;
Fügen Sie in der
Main()
-Methode innerhalb derusing
-Anweisung dem Diensthost eine ServiceDiscoveryBehavior-Instanz hinzu.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()); // ... } }
Das ServiceDiscoveryBehavior-Objekt gibt an, dass der Dienst, auf den dieses Verhalten angewendet wird, erkennbar ist.
Fügen Sie dem Diensthost direkt nach dem Code, in dem UdpDiscoveryEndpoint hinzugefügt wird, ein ServiceDiscoveryBehavior-Objekt hinzu.
// Add ServiceDiscoveryBehavior serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); // Add a UdpDiscoveryEndpoint serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Dieser Code gibt an, dass Suchmeldungen an den standardmäßigen UDP-Suchendpunkt gesendet werden sollen.
So erstellen Sie eine Clientanwendung, die die Suche zum Aufrufen des Diensts verwendet
Fügen Sie der Projektmappe eine neue Konsolenanwendung mit dem Namen
DiscoveryClientApp
hinzu.Fügen Sie einen Verweis auf
System.ServiceModel.dll
undSystem.ServiceModel.Discovery.dll
hinzu.Kopieren Sie die Dateien "GeneratedClient.cs" und "App.config" aus dem vorhandenen Clientprojekt in das neue DiscoveryClientApp-Projekt. Klicken Sie hierzu im Projektmappen-Explorer mit der rechten Maustaste auf die Dateien, wählen Sie Kopieren aus, und wählen Sie dann das Projekt DiscoveryClientApp aus. Klicken Sie mit der rechten Maustaste, und wählen Sie Einfügen aus.
Öffnen Sie die Datei Program.cs.
Fügen Sie die folgenden
using
-Anweisung hinzu.using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
Fügen Sie der
FindCalculatorServiceAddress()
-Klasse eine statische Methode mit dem NamenProgram
hinzu.static EndpointAddress FindCalculatorServiceAddress() { }
Diese Methode verwendet die Suche (Discovery) zum Suchen nach dem
CalculatorService
-Dienst.Erstellen Sie in der
FindCalculatorServiceAddress
-Methode eine neue DiscoveryClient-Instanz, die einen UdpDiscoveryEndpoint an den Konstruktor übergibt.static EndpointAddress FindCalculatorServiceAddress() { // Create DiscoveryClient DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); }
Auf diese Weise wird WCF mitgeteilt, dass die DiscoveryClient-Klasse den standardmäßigen UDP-Ermittlungsendpunkt zum Senden und Empfangen von Ermittlungsmeldungen verwenden soll.
Rufen Sie in der nächsten Zeile die Find-Methode auf, und geben Sie eine FindCriteria-Instanz an, die den zu suchenden Dienstvertrag enthält. Geben Sie in diesem Fall
ICalculator
an.// Find ICalculatorService endpoints FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
Überprüfen Sie nach dem Aufruf von Find, ob mindestens ein übereinstimmender Dienst vorhanden ist, und geben Sie für den ersten übereinstimmenden Dienst EndpointAddress zurück. Geben Sie andernfalls
null
zurück.if (findResponse.Endpoints.Count > 0) { return findResponse.Endpoints[0].Address; } else { return null; }
Fügen Sie der
InvokeCalculatorService
-Klasse eine statische Methode mit dem NamenProgram
hinzu.static void InvokeCalculatorService(EndpointAddress endpointAddress) { }
Diese Methode verwendet die von
FindCalculatorServiceAddress
zurückgegebene Endpunktadresse zum Aufrufen des Rechnerdiensts.Erstellen Sie innerhalb der
InvokeCalculatorService
-Methode eine Instanz derCalculatorServiceClient
-Klasse. Diese Klasse wird im Beispiel für selbst gehostete Dienste definiert. Sie wurde mithilfe von "Svcutil.exe" generiert.// Create a client CalculatorClient client = new CalculatorClient();
Legen Sie in der nächsten Zeile die Endpunktadresse des Clients auf die Endpunktadresse fest, die von
FindCalculatorServiceAddress()
zurückgegeben wurde.// Connect to the discovered service endpoint client.Endpoint.Address = endpointAddress;
Rufen Sie direkt nach dem Code für den vorherigen Schritt die vom Rechnerdienst verfügbar gemachten Methoden auf.
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();
Fügen Sie der
Main()
-Methode in derProgram
-Klasse Code zum Aufrufen vonFindCalculatorServiceAddress
hinzu.public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
Rufen Sie in der nächsten Zeile
InvokeCalculatorService()
auf, und übergeben Sie die Endpunktadresse, die vonFindCalculatorServiceAddress()
zurückgegeben wurde.if (endpointAddress != null) { InvokeCalculatorService(endpointAddress); } Console.WriteLine("Press <ENTER> to exit."); Console.ReadLine();
So testen Sie die Anwendung
Öffnen Sie eine Eingabeaufforderung mit erhöhten Rechte, und führen Sie "Service.exe" aus.
Öffnen Sie eine Eingabeaufforderung, und führen Sie "Discoveryclientapp.exe" aus.
Die Ausgabe der Datei "service.exe" sollte der folgenden Ausgabe ähneln.
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
Die Ausgabe der Datei "Discoveryclientapp.exe" sollte der folgenden Ausgabe ähneln.
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.
Beispiel
Es folgt eine Auflistung des Codes für dieses Beispiel. Da dieser Code auf dem Beispiel für selbst gehostete Dienste basiert, sind nur die geänderten Dateien aufgeführt.
// 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();
}
}
}