方法: プログラムを使用して探索可能性に 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 が必要です" が表示されることがあります。このメッセージが表示された場合は、ソリューション エクスプローラーでプロジェクトを右クリックし、 [プロパティ] をクリックします。 [プロジェクトのプロパティ] ウィンドウで、[ターゲット フレームワーク] が .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.dll および System.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 への呼び出しの後で、一致するサービスが少なくとも 1 つあるかどうかを確認し、最初に一致したサービスの 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();

        }
    }
}

関連項目