メッセージ交換のサンプル

Download sample

このサンプルでは、ワークフロー サービスが、同じコントラクトで複数のクライアントと並行してメッセージ交換を行う方法を示します。サンプルでは、同じコントラクトと同じ操作に対して送信されるが、送信元のクライアントが異なるので別の方法で処理する必要があるメッセージを関連付ける方法を示します。並行してメッセージ交換を行うため、このサンプルではワークフロー サービスから提供されているメッセージ交換コンテキスト機能を使用します。

Noteメモ :

このサンプルをビルドして実行するには、.NET Framework Version 3.5 をインストールする必要があります。Visual Studio 2008 では、プロジェクトとソリューション ファイルを開く必要があります。

このサンプルのセットアップの詳細については、「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」を参照してください。

このサンプルでは、ワークフロー サービスとクライアントが非同期に通信できるように、非同期双方向通信も使用します。双方向通信の場合、通信が開始される前に 2 つのアプリケーションでコンテキストを交換する必要があります。メッセージ交換を開始した側のサービスは、メッセージの返信としてコンテキストを受け取ります。ワークフロー サービスでこの機能が提供されます。受信側サービスから開始側サービスへの通信をサポートするには、開始側サービスがそのコンテキスト情報を最初のメッセージで送信する必要があります。このサンプルのアーキテクチャを図 1 に示します。

メッセージ交換のサンプル アーキテクチャ

図 1: メッセージ交換のサンプル

このサンプルでは次のシナリオを実装します。

顧客が注文要求を送信します。この要求に対して、サプライヤは商品を発送する 3 つの物流担当会社から見積もりを出してもらいたいと思います。サプライヤはこの 3 つのサプライヤにメッセージを送信します。各プロバイダは、同じコントラクトの同じ操作を呼び出して見積もりを返送します。サプライヤ ワークフローではメッセージ交換コンテキストを使用しているため、この機能で見積もりを正しい受信動作に関連付けて、処理を進めることができます。サプライヤはすべての見積もりを受け取り、最も低価格の見積もりを選んで、それを顧客に送信します。

このサンプルでは 5 つのエンティティが通信を行います。

  • カスタマ サービス

    カスタマ サービスでは、サプライヤ サービスが後でカスタマ サービスとの通信に使用するコンテキストと共に、注文の詳細をサプライヤに送信します。この基本ワークフローには、発注書およびコンテキストをペイロードとした発注書要求メッセージを送信する、最初の送信アクティビティが含まれています。受信アクティビティはサプライヤ サービスからの応答を待ちます。

    カスタマ サービスが送信するコンテキストは、受信アクティビティに関連付けられています。送信アクティビティの "before send" ハンドラには、受信アクティビティからコンテキストを取得するコードが含まれています。受信アクティビティには、コンテキストを取得するために呼び出される次の GetContext メソッドが含まれています。

    private void PrepareOrder(object sender, SendActivityEventArgs e)
    {
        this.order.Amount = 1000;
        this.order.OrderId = 1234;
        this.contextToSend = this.ReceiveOrderDetails.Context;
    }
    
  • サプライヤ サービス

    サプライヤ サービスは、3 つの物流担当プロバイダと通信します。サプライヤ サービスは通信を行うために、各メッセージ交換と非同期双方向通信に一意のコンテキスト トークンの組み合わせを使用します。このトークンは、カスタマ サービスとサプライヤ サービス間の通信のメッセージ本文のコンテキストを送信します。

    物流担当プロバイダと通信する前に、サプライヤ サービスは最初にカスタマ サービスからメッセージを受信します。このメッセージでは、サプライヤ サービスはカスタマ サービスと連絡を取るために使用するコンテキストも一緒に受信します。サプライヤ サービス ワークフローは、クライアント サービスへのメッセージ送信に使用する Send アクティビティにこのコンテキストを適用します。この機能を実装するコードは、次のコードに示すように、最初の受信アクティビティ内のコード アクティビティのコード ハンドラ内に存在します。

    private void AcceptOrder(object sender, EventArgs e)
    {
        Console.WriteLine("Order Received...");
        this.supplierAck = "Order Received on " + DateTime.Now;
        this.SendOrderDetails.Context = this.customerContext;
    }
    

    サプライヤ サービスが顧客からメッセージを受け取ると、サプライヤは 3 つの物流担当プロバイダと 3 つの並行メッセージ交換を開始します。各メッセージ交換の分岐には、前の図に示すように Send アクティビティと Receive アクティビティがあります。各分岐の Send アクティビティは、1 つの物流担当サプライヤにメッセージを送信します。その分岐で対応する Receive アクティビティは、サプライヤからメッセージを取得する必要があります。そのためには、メッセージ ペイロードの Send アクティビティでペイロードの一意のコンテキストを送信する必要があります。物流担当プロバイダは、見積もりと共にメッセージを返送するときに、メッセージ ヘッダーでこのコンテキストを使用します。

    既定では、すべての Receive アクティビティにルート コンテキストがあります。Receive アクティビティを一意にするため、Receive アクティビティはルート アクティビティ以外の親アクティビティにコピーされるコンテキストを定義します。次のサンプルでは、並行会話の各 Receive アクティビティのコンテキスト トークン プロパティに一意の名前があり、そのプロパティが含まれる並行アクティビティが対象範囲となっています。それぞれの並行分岐の送信アクティビティが受信アクティビティからコンテキストを受け取ると、そのReceive アクティビティに一意のコンテキストが取得されます。この一意のコンテキストは、受信アクティビティがリッスンしているキューのキュー名の作成にも使用されます。物流担当プロバイダがそのヘッダーのコンテキストと一緒に見積もりを送信すると、ワークフロー サービス ディスパッチ レイヤはこれを使用して適切なキュー名を作成し、メッセージをキューに配置します。これを Receive アクティビティが確認します。

    private void PrepareShipper2Request(object sender, SendActivityEventArgs e)

    {

    Console.ForegroundColor = ConsoleColor.Green;

    Console.WriteLine("RequestShippingQuote from Shipper2");

    Console.ResetColor();

    this.contextShipper2 = this.ReceiveQuoteFromShipper2.Context;

    }

    物流担当プロバイダのワークフローは、サプライヤからコンテキストと一緒に見積もり要求を受け取ります。そのコンテキストは、次のコードに示すように、メッセージをサプライヤに返送する送信アクティビティに適用されます。

    private void AcceptQuoteRequest(object sender, EventArgs e)
    {
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine("Received ShippingQuote Request");
        this.supplierAck = "Working on quote...";
        Console.ResetColor();
        this.SendShippingQuote.Context(this.supplierContext);
    }
    

サンプルをセットアップ、ビルド、および実行するには

  1. 既定では、このサンプルでは永続化は使用されません。永続化を使用する場合は、各ソリューションの App.config ファイルに <WorkflowRuntime> エントリを追加します。エントリは次の例に示すように behaviors セクションにあります。

    <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior"  >
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="true" />
              <workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true" enablePerformanceCounters="true">
                <services>
                  <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                       connectionString="Data Source=localhost\sqlexpress;Initial Catalog=ServiceModelSamples_ServiceWorkflowStore;Integrated Security=True;Pooling=False"
                       LoadIntervalSeconds="1" UnLoadOnIdle= "true" />
                </services>
              </workflowRuntime>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
  2. behaviors セクションの <WorkflowRuntime> エントリに加えて、SQL 永続化サービスも追加されます。「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」に示した Createstores.cmd スクリプトを実行します。CreateStores.cmd スクリプトは ServiceModelSamples_ServiceWorkflowStore データベースを作成します。既定では、これらのデータベースは SQL Server 2005 Express Edition データベースに作成されます。SQL Server Express がコンピュータにインストールされていることを確認してください。SQL Server Express をインストールせずに SQL Server を代わりに使用する場合は、App.config ファイルの接続文字列を永続化データベース用に変更してください。

  3. すべてのワークフロー サービスが実行されたら、クライアント ワークフローで Enter キーを押すと、相互に通信しているすべてのワークフローが表示されます。発注書がサプライヤに送信され、サプライヤはすべての物流担当サプライヤに物流担当プロバイダの見積もり要求を送信します。サプライヤが見積もりを受け取ると、最低額の見積もりが顧客に送信されることが確認できます。また、各場合のコンテキスト トークンも確認できます。確認すると、各物流担当プロバイダに送信される一意のコンテキストを理解できます。

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.