Как программно добавить возможность обнаружения к службе и клиенту WCF
В этом разделе объясняется, как сделать службу Windows Communication Foundation (WCF) обнаруживаемой. Он основан на примере самостоятельного узла .
Настройка образца службы существующего резидентного размещения для обнаружения
Откройте решение самообслуживания в Visual Studio 2012. Образец находится в каталоге TechnologySamples\Basic\Service\Hosting\SelfHost.
Добавьте ссылку на проект службы
System.ServiceModel.Discovery.dll
. Вы можете увидеть сообщение об ошибке с фразой "Система. для ServiceModel.Discovery.dll или одной из зависимостей требуется более поздняя версия платформа .NET Framework, чем указанная в проекте ..." Если вы видите это сообщение, щелкните проект правой кнопкой мыши в Обозреватель решений и выберите "Свойства". В окне "Свойства проекта" убедитесь, что целевая платформа платформа .NET Framework 4.6.1.Откройте файл Service.cs и добавьте следующую
using
директиву.using System.ServiceModel.Discovery;
В методе
Main()
в инструкцииusing
добавьте экземпляр ServiceDiscoveryBehavior в узел службы.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 указывает, что служба, к которой оно применяется, доступна для обнаружения.
Добавьте UdpDiscoveryEndpoint в узел службы сразу после кода, добавляющего ServiceDiscoveryBehavior.
// Add ServiceDiscoveryBehavior serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); // Add a UdpDiscoveryEndpoint serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Этот код указывает, что сообщения об обнаружении должны отправляться стандартной конечной точке обнаружения UDP.
Создание клиентского приложения, использующего обнаружение при вызове службы
Добавьте в решение новое консольное приложение с именем
DiscoveryClientApp
.Добавьте ссылку на сборки
System.ServiceModel.dll
иSystem.ServiceModel.Discovery.dll
.Скопируйте файлы GeneratedClient.cs и App.config из существующего проекта клиента в новый проект DiscoveryClientApp. Для этого щелкните правой кнопкой мыши файлы в Обозреватель решений, выберите "Копировать", а затем выберите проект DiscoveryClientApp, щелкните правой кнопкой мыши и выберите "Вставить".
Откройте Program.cs.
Добавьте следующие
using
директивы.using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
Добавьте статический метод с именем
FindCalculatorServiceAddress()
в классProgram
.static EndpointAddress FindCalculatorServiceAddress() { }
Этот метод использует обнаружение для поиска службы
CalculatorService
.Внутри метода
FindCalculatorServiceAddress
создайте новый экземпляр DiscoveryClient, передав UdpDiscoveryEndpoint в конструктор.static EndpointAddress FindCalculatorServiceAddress() { // Create DiscoveryClient DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); }
Это сообщает WCF, что DiscoveryClient класс должен использовать стандартную конечную точку обнаружения UDP для отправки и получения сообщений об обнаружении.
В следующей строке вызовите метод Find и укажите экземпляр FindCriteria, содержащий контракт службы, который необходимо найти. В данном случае укажите
ICalculator
.// Find ICalculatorService endpoints FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
После вызова Find проверьте наличие хотя бы одной соответствующей службы и верните EndpointAddress первой из найденных. В противном случае верните значение
null
.if (findResponse.Endpoints.Count > 0) { return findResponse.Endpoints[0].Address; } else { return null; }
Добавьте статический метод с именем
InvokeCalculatorService
в классProgram
.static void InvokeCalculatorService(EndpointAddress endpointAddress) { }
Этот метод использует для вызова службы калькулятора адрес конечной точки, возвращенной из
FindCalculatorServiceAddress
.Внутри метода
InvokeCalculatorService
создайте экземпляр классаCalculatorServiceClient
. Этот класс определяется примером самостоятельного узла . Он был сформирован с помощью программы Svcutil.exe.// Create a client CalculatorClient client = new CalculatorClient();
В следующей строке укажите адрес конечной точки клиента в адресе конечной точки, возвращенном методом
FindCalculatorServiceAddress()
.// 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();
Добавьте в метод
Main()
классаProgram
код для вызоваFindCalculatorServiceAddress
.public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
В следующей строке вызовите метод
InvokeCalculatorService()
и передайте конечной точке адрес, возвращенный методомFindCalculatorServiceAddress()
.if (endpointAddress != null) { InvokeCalculatorService(endpointAddress); } Console.WriteLine("Press <ENTER> to exit."); Console.ReadLine();
Тестирование приложения
Откройте командную строку с правами администратора и запустите программу Service.exe.
Откройте окно командной строки и запустите программу Discoveryclientapp.exe.
Результатом выполнения service.exe должен быть следующий вывод.
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
Результатом выполнения Discoveryclientapp.exe должен быть следующий вывод.
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.
Пример
Ниже приведен полный листинг кода для данного образца. Так как этот код основан на примере самообслуживания, перечислены только те файлы, которые изменяются.
// 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();
}
}
}