Share via


方法 : Silverlight クライアントで双方向サービスを構築する

ここでは、Windows Communication Foundation (WCF) クライアントとの通信が可能な双方向 Silverlight サービスを作成する方法を説明します。双方向サービスでは、Silverlight クライアントへのコールバック チャネルを管理することによって、クライアントに対する呼び出しを実行可能にします。双方向サービスには、インスタント メッセージングのチャット サーバーや、クライアントに通知を送信する監視サービスをはじめとした多数のアプリケーションがあります。このサンプルでは、指定された数の品目をクライアントから名前で注文できるようにするサービスを示します。サービスでは注文の処理をシミュレートしてから、注文ステータスをクライアントに返信します。

双方向のメッセージングでは、サービスとクライアントの両方がサービス コントラクトを公開します。このコントラクトによってそれぞれが互いに公開する操作が指定されます。この例では、次のペアのサービス コントラクトを使用します。クライアントはサービスの Order メソッドを呼び出し、サービスはクライアントの Receive メソッドを呼び出します。

[ServiceContract(Namespace="Silverlight", CallbackContract = typeof(IDuplexClient))]
public interface IDuplexService
{
    [OperationContract(IsOneWay = true)]
    void Order(string name, int quantity);
}

[ServiceContract]
public interface IDuplexClient
{
    [OperationContract(IsOneWay = true)]
    void Receive();
}

サービスに対してクライアントをコールバックするコントラクトを指定するには、CallbackContract プロパティを使用します。

また、サービス コントラクトに含まれるサービス メソッドのそれぞれに対しては、OperationContractAttributeIsOneWay プロパティを true に設定します。同様に、サービス コントラクトに含まれるクライアント メソッドのそれぞれについても OperationContractAttributeIsOneWay プロパティを true に設定する必要があります。このプロパティによって、これらの操作では応答メッセージが返されないことが指定されます。

Silverlight で機能する WCF 双方向サービスを作成するには

  1. Visual Studio 2008 を開きます。

  2. [ファイル] メニューで、[新規][プロジェクト] の順に選択し、コーディングに使用する言語 (C# または Visual Basic) グループの、左側に一覧表示される [プロジェクトの種類][Web] を指定します。次に、右側の [テンプレート] から [WCF サービス アプリケーション] を選択して、下の [名前] ボックスで「DuplexService」と名前を付け、[OK] をクリックします。

  3. ソリューション エクスプローラー[DuplexService] プロジェクトを右クリックして、[参照の追加] を選択します。[ブラウザー] タブをクリックして、%ProgramFiles%\Microsoft SDKs\Silverlight\v3.0\Libraries\Server\ ディレクトリにあるアセンブリ System.ServiceModel.PollingDuplex.dll に移動して選択し、[OK] をクリックします。

    Dd470106.Warning(ja-jp,VS.95).gif 注意 :
    Silverlight Version 3 SDK には、System.ServiceModel.PollingDuplex.dll という名前のアセンブリが 2 つ付属しているため、注意が必要です。先ほど参照を追加した、そのうちの 1 つ (%ProgramFiles%\Microsoft SDKs\Silverlight\v3.0\Libraries\Server\ ディレクトリに格納) は、WCF 双方向サービスによって使用されます。もう 1 つのアセンブリ (%ProgramFiles%\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\ ディレクトリに格納) は、Silverlight 双方向クライアントで使用されます。前の手順に正確に従って正しい場所に移動し、適切な双方向サービスのアセンブリと双方向クライアント アプリケーションのアセンブリを順に参照する必要があります。

  4. IService1.cs ファイルの既定のコンテンツを DuplexService 名前空間の次のコードに置き換えます。このコードでは、interfaces を使用してサービスとクライアントの両方で使用されるコントラクトを定義します。

    //Interface contracts in the IService1.cs file.
    
    namespace DuplexService
    {
        [ServiceContract(Namespace="Silverlight", CallbackContract = typeof(IDuplexClient))]
        public interface IDuplexService
        {
            [OperationContract(IsOneWay = true)]
            void Order(string name, int quantity);
        }
    
        [ServiceContract]
        public interface IDuplexClient
        {
            [OperationContract(IsOneWay = true)]
            void Receive(Order order);
        }
    }
    

    このコードは、このトピックの導入部分で WCF サービスと Silverlight クライアント間での双方向通信の特徴と、使用されるメッセージ パターンを定義するためにそれらが公開するサービス コントラクトについて説明したときに示したコードと同じものです。

  5. Service1.svc.cs ファイルの先頭に次の using ステートメントを追加します。

    using System.Threading;
    

    この名前空間の機能は、サンプルの双方向サービスで実際のサービスの処理遅延動作をシミュレートするために使用されます。

  6. Service1.svc.cs ファイルのコンテンツを編集して、IDuplexService コントラクトを実装する OrderService クラスを定義します。まず、DuplexService 名前空間の宣言内にあるすべてのクラスを削除します。その後、次のコードのように OrderService クラスを定義します。

    public class OrderService : IDuplexService
        {
            IDuplexClient client;
            string orderName;
            int orderQuantity;
    
            public void Order(string name, int quantity)
            {
                // Grab the client callback channel.
                client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
                orderName = name;
                orderQuantity = quantity;
    
                // Pretend service is processing and will call client back in 5 seconds.
                using (Timer timer = new Timer(new TimerCallback(CallClient), null, 5000, 5000))
                {
                    Thread.Sleep(11000);
    
                }
            }
    }
    

    Order の処理では、オンライン ストアの品目の注文プロセスの実行がシミュレートされます。受注すると、その後の一連のアクションは、通常はこのサービスの範囲外で実行されます (例 : 品目の在庫確認、ユーザーのクレジット カード情報の確認など)。これらのアクションが完了してから、サービスでクライアントをコールバックして (つまり、情報をクライアントにプッシュして)、注文が正常に完了したことを通知します。このシナリオをシミュレートするために、5 秒の間隔を 2 回置いてからサービスを 2 回呼び出す Timer を使用します。

    IDuplexClient 型のコールバック チャネルを取得する OperationContext.GetCallbackChannel(T) メソッドの使用に注意します。これは、実装および実行後の Silverlight クライアントへの接続に使用されます。

  7. DuplexService 名前空間内で Order クラスと補助的な OrderStatus 列挙型を追加し、サービスがクライアントに返すことのできる注文に関する情報を表します。

    public class Order
    {
        public OrderStatus Status { get; set; }
        public List<string> Payload { get; set; }
    }
    
    public enum OrderStatus
    {
        Processing,
        Completed
    }
    
  8. OrderService クラス内で、以下を追加します。

    bool processed = false;
    
    private void CallClient(object o)
    {
        Order order = new Order();
        order.Payload = new List<string>();
    
        // Process order.
        if (processed)
        {
            // Pretend service is fulfilling the order.
            while (orderQuantity-- > 0)
            {
                order.Payload.Add(orderName + orderQuantity);
            }
    
            order.Status = OrderStatus.Completed;
    
        }
        else
        {
            // Pretend service is processing payment.
            order.Status = OrderStatus.Processing;
            processed = true;
        }
    
        // Call client back.
        client.Receive(order);
    
    }
    

    サービスの注文処理アクティビティをシミュレートするため、このメソッドは 2 回呼び出されます。1 回目の呼び出しでは、注文が処理中であることがレポートされます。2 回目の呼び出しでは、注文が完了したことがレポートされ、注文の Payload プロパティが設定されます。

  9. Service1.svc ファイルで Service の値を編集して、DuplexService.OrderService を指定します。ソリューション エクスプローラーで Service1.svc ファイルを右クリックし、[マークアップの表示] を選択して、既定のディレクティブに次のサービス ディレクティブを貼り付けます。

    // Directive contained in the Service1.scv file.
    
    <%@ServiceHost language="c#" Debug="true" Service="DuplexService.OrderService" CodeBehind="Service1.svc.cs "%>
    
  10. ソリューション エクスプローラーで Web.config ファイルを右クリックし、[開く] をクリックして構成を編集します。最初に、<bindingsExtensions> セクションで Silverlight 3 SDK から pollingDuplexHttpBinding を登録します。

    <!-- Register the binding extension from the SDK. -->
        <extensions>
          <bindingExtensions>
            <add name="pollingDuplexHttpBinding"
       type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </bindingExtensions>
        </extensions>
    

    次に、<bindings> セクションで pollingDuplexHttpBinding を作成します。

    
      <bindings>
        <pollingDuplexHttpBinding />
      </bindings>
    

    そして、<services> セクションでサービス エンドポイントを指定します。

        <services>
          <service name="DuplexService.OrderService"
                   behaviorConfiguration="DuplexService.OrderServiceBehavior">
    
            <!-- Service Endpoints -->
            <endpoint address=""
                      binding="pollingDuplexHttpBinding"
                      contract="DuplexService.IDuplexService">
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
    

    この結果、Web.config ファイルの <system.serviceModel> セクションには、次の構成要素が含まれています。

    //The  <system.serviceModel> section of the Web.config file.
    
      <system.serviceModel>
    
      <!-- Register binding extension from SDK. -->
      <extensions>
      <bindingExtensions>
      <add name="pollingDuplexHttpBinding"
    type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </bindingExtensions>
      </extensions>
    
      <!-- Create the polling duplex binding. -->
      <bindings>
      <pollingDuplexHttpBinding />
      </bindings>
    
        <services>
          <service name="DuplexService.OrderService"
                   behaviorConfiguration="DuplexService.OrderServiceBehavior">
    
            <!-- Specify the service endpoints. -->
            <endpoint address=""
                      binding="pollingDuplexHttpBinding"
                      contract="DuplexService.IDuplexService">
            </endpoint>
            <endpoint address="mex"
                      binding="mexHttpBinding"
                      contract="IMetadataExchange"/>
          </service>
        </services>
    
        <behaviors>
          <serviceBehaviors>
            <behavior name="DuplexService.OrderServiceBehavior">
              <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
              <serviceMetadata httpGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
      </system.serviceModel>
    
  11. これで、双方向サービスのテストを実行できます。ソリューション エクスプローラーで Service1.svc ファイルを選択して右クリックし、[ブラウザーで表示] を選択して (または Ctrl キーを押しながら F5 キーを押して)、サービスのテスト ページを表示します。ServiceOrder Service のテスト ページが表示されます。これにより、サービスが使用できることが確認できます。

これで、双方向サービスを使用できるようになりました。次の手順では、このサービスに対して Silverlight クライアントを構築します。この手順については、「方法 : 双方向サービスにアクセスする」に概要が示されています。

Service1.svc.cs ファイルには次のコンテンツが必要です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading;

namespace DuplexService
{
    public class OrderService : IDuplexService
    {
        IDuplexClient client;
        string orderName;
        int orderQuantity;

        public void Order(string name, int quantity)
        {
            // Grab the client callback channel.
            client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
            orderName = name;
            orderQuantity = quantity;

            // Pretend the service is processing and will call the client
            // back in 5 seconds.
            using (Timer timer = new Timer(new TimerCallback(CallClient), null, 5000, 5000))
            {
                Thread.Sleep(11000);

            }
        }

        bool processed = false;

        private void CallClient(object o)
        {
            Order order = new Order();
            order.Payload = new List<string>();

            // Process the order.
            if (processed)
            {
                // Pretend the service is fulfilling the order.
                while (orderQuantity-- > 0)
                {
                    order.Payload.Add(orderName + orderQuantity);
                }

                order.Status = OrderStatus.Completed;

            }
            else
            {
                // Pretend the service is processing the payment.
                order.Status = OrderStatus.Processing;
                processed = true;
            }

            // Call the client back.
            client.Receive(order);

        }

    }

    public class Order
    {
        public OrderStatus Status { get; set; }
        public List<string> Payload { get; set; }
    }

    public enum OrderStatus
    {
        Processing,
        Completed
    }

}

関連項目

タスク

方法 : 双方向サービスにアクセスする
ドメインの境界を越えてサービスを利用できるようにする

このトピックに関するコメントを Microsoft に送信する。

Copyright© 2009 by Microsoft Corporation. All rights reserved.