共用方式為


作法:以程式設計方式將探索能力新增至 WCF 服務與用戶端

本主題說明如何讓 Windows Communication Foundation (WCF) 服務可供搜尋。 它是以自我裝載範例為基礎。

若要為探索設定現有的自我裝載服務範例

  1. 在 Visual Studio 2012 中開啟自我裝載解決方案。 範例位於 TechnologySamples\Basic\Service\Hosting\SelfHost 目錄中。

  2. System.ServiceModel.Discovery.dll的參考加入至服務專案。 您可能會看到此錯誤訊息,「System. ServiceModel.Discovery.dll 或其中一個相依性需要較專案中所指定之 .NET Framework 版本更新的版本…」。如果看見此訊息,請以滑鼠右鍵按一下 [方案總管] 中的專案,然後選擇 [屬性]。 在 [專案屬性] 視窗中,確定 [目標 Framework] 為 .NET Framework 4.6.1。

  3. 開啟Service.cs檔案,然後新增下列 using 指示詞。

    using System.ServiceModel.Discovery;
    
  4. 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 會指定所套用的服務成為可探索狀態。

  5. 在加入 UdpDiscoveryEndpoint 程式碼的後方直接將 ServiceDiscoveryBehavior 加入至服務主機。

    // Add ServiceDiscoveryBehavior
    serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
    
    // Add a UdpDiscoveryEndpoint
    serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
    

    此程式碼會指定探索訊息應傳送至標準 UDP 探索端點。

若要建立使用探索來呼叫服務的用戶端應用程式

  1. 將新主控台應用程式加入至名為 DiscoveryClientApp 的方案。

  2. 將參考加入至 System.ServiceModel.dllSystem.ServiceModel.Discovery.dll

  3. 從現有的用戶端專案複製 GeneratedClient.cs 和 App.config 檔案並貼上至 DiscoveryClientApp 專案。 若要這樣做,請以滑鼠右鍵按一下 [方案總管] 中的檔案,選取 [複製],然後選取 [DiscoveryClientApp] 專案,按一下滑鼠右鍵並選取 [貼上]

  4. 開啟 Program.cs。

  5. 新增下列 using 指示詞。

    using System.ServiceModel;
    using System.ServiceModel.Discovery;
    using Microsoft.ServiceModel.Samples;
    
  6. 將名為 FindCalculatorServiceAddress() 的靜態方法加入至 Program 類別。

    static EndpointAddress FindCalculatorServiceAddress()
    {
    }
    

    這個方法會使用探索來搜尋 CalculatorService 服務。

  7. FindCalculatorServiceAddress 方法中,建立新的 DiscoveryClient 執行個體,傳入 UdpDiscoveryEndpoint 至建構函式。

    static EndpointAddress FindCalculatorServiceAddress()
    {
        // Create DiscoveryClient
        DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
    }
    

    這樣做可告知 WCF,DiscoveryClient 類別應使用標準 UDP 探索端點來傳送和接收探索訊息。

  8. 在下一行,呼叫 Find 方法並指定包含要搜尋之服務合約的 FindCriteria 執行個體。 在此情況下,指定 ICalculator

    // Find ICalculatorService endpoints
    FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
    
  9. 呼叫 Find 後,查看是否至少有一個符合的服務,然後傳回第一個符合服務的 EndpointAddress。 否則,傳回 null

    if (findResponse.Endpoints.Count > 0)
    {
        return findResponse.Endpoints[0].Address;
    }
    else
    {
        return null;
    }
    
  10. 將名為 InvokeCalculatorService 的靜態方法加入至 Program 類別。

    static void InvokeCalculatorService(EndpointAddress endpointAddress)
    {
    }
    

    此方法使用自 FindCalculatorServiceAddress 傳回的端點位址來呼叫計算機服務。

  11. InvokeCalculatorService 方法中,建立 CalculatorServiceClient 類別的執行個體。 此類別是由自我裝載範例所定義。 它是使用 Svcutil.exe 來產生的。

    // Create a client
    CalculatorClient client = new CalculatorClient();
    
  12. 在下一行,將用戶端的端點位址設為從 FindCalculatorServiceAddress() 傳回的端點位址。

    // Connect to the discovered service endpoint
    client.Endpoint.Address = endpointAddress;
    
  13. 在前述的程式碼步驟之後,立即呼叫由計算機服務所公開的方法。

    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();
    
  14. Main() 類別中將程式碼加入至 Program 方法來呼叫 FindCalculatorServiceAddress

    public static void Main()
    {
        EndpointAddress endpointAddress = FindCalculatorServiceAddress();
    }
    
  15. 在下一行,呼叫 InvokeCalculatorService() 並傳入從 FindCalculatorServiceAddress() 傳回的端點位址。

    if (endpointAddress != null)
    {
        InvokeCalculatorService(endpointAddress);
    }
    
    Console.WriteLine("Press <ENTER> to exit.");
    Console.ReadLine();
    

若要測試應用程式

  1. 開啟更高權限的命令提示字元,然後執行 Service.exe。

  2. 開啟命令提示字元並執行 Discoveryclientapp.exe。

  3. 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
    
  4. 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();

        }
    }
}

另請參閱