次の方法で共有


操作フォーマッタと操作セレクター

QueryStringFormatter サンプルでは、Windows Communication Foundation (WCF) の機能拡張ポイントを使用して、WCF が想定する形式とは異なる形式のメッセージ データを許可する方法を示します。 既定では、WCF フォーマッタはメソッド パラメーターが soap:body 要素の下に含まれることを想定しています。 このサンプルでは、代わりに HTTP GET クエリ文字列からパラメーター データを解析し、そのデータを使用してメソッドを呼び出すカスタム操作フォーマッタを実装する方法を示します。

このサンプルは、 サービス コントラクトを実装するICalculatorに基づいています。 クライアントからサーバーへの要求に HTTP GET を使用するようにメッセージを追加、減算、乗算、および除算し、サーバーからクライアントへの応答に POX メッセージを含む HTTP POST を使用する方法を示します。

これを行うために、サンプルには次のものが用意されています。

  • QueryStringFormatter: クライアントとサーバーの IClientMessageFormatterIDispatchMessageFormatter をそれぞれ実装し、クエリ文字列内のデータを処理します。

  • UriOperationSelectorは、GET 要求の操作名に基づいて操作ディスパッチを実行する IDispatchOperationSelector をサーバーに実装します。

  • EnableHttpGetRequestsBehavior エンドポイントの動作 (および対応する構成) 。これにより、必要な操作セレクターがランタイムに追加されます。

  • 新しい操作フォーマッタをランタイムに挿入する方法を示します。

  • このサンプルでは、クライアントとサービスの両方がコンソール アプリケーション (.exe) です。

このサンプルのセットアップ手順とビルド手順は、このトピックの最後にあります。

主要概念

QueryStringFormatter - 操作フォーマッタは、メッセージをパラメーター オブジェクトの配列に変換し、パラメーター オブジェクトの配列をメッセージに変換する WCF のコンポーネントです。 これは、 IClientMessageFormatter インターフェイスを使用するクライアントと、 IDispatchMessageFormatter インターフェイスを持つサーバー上で行われます。 これらのインターフェイスを使用すると、ユーザーは Serialize メソッドと Deserialize メソッドから要求メッセージと応答メッセージを取得できます。

このサンプルでは、 QueryStringFormatter これらのインターフェイスの両方を実装し、クライアントとサーバーに実装します。

依頼:

  • このサンプルでは、 TypeConverter クラスを使用して、要求メッセージ内のパラメーター データを文字列との間で変換します。 特定の型に対して TypeConverter を使用できない場合、サンプル フォーマッタは例外をスローします。

  • クライアントの IClientMessageFormatter.SerializeRequest メソッドでは、フォーマッタは適切な To アドレスを持つ URI を作成し、操作名をサフィックスとして追加します。 この名前は、サーバー上の適切な操作にディスパッチするために使用されます。 次に、パラメーター オブジェクトの配列を受け取り、パラメーター名と、 TypeConverter クラスによって変換された値を使用して、パラメーター データを URI クエリ文字列にシリアル化します。 その後、 To プロパティと Via プロパティがこの URI に設定されます。 MessageProperties は、 Properties プロパティを介してアクセスされます。

  • サーバー上の IDispatchMessageFormatter.DeserializeRequest メソッドでは、フォーマッタは受信要求メッセージプロパティの Via URI を取得します。 URI クエリ文字列内の名前と値のペアをパラメーターの名前と値に解析し、パラメーターの名前と値を使用して、メソッドに渡されるパラメーターの配列を設定します。 操作ディスパッチが既に発生しているため、このメソッドでは操作名のサフィックスは無視されることに注意してください。

応答:

  • このサンプルでは、HTTP GET は要求にのみ使用されます。 フォーマッタは、XML メッセージの生成に使用された元のフォーマッタへの応答の送信を委任します。 このサンプルの目的の 1 つは、このような委任フォーマッタを実装する方法を示することです。

UriPathSuffixOperationSelector クラス

IDispatchOperationSelector インターフェイスを使用すると、ユーザーは、特定のメッセージをディスパッチする操作に対して独自のロジックを実装できます。

このサンプルでは、操作名がメッセージのアクション ヘッダーではなく HTTP GET URI に含まれているため、 UriPathSuffixOperationSelector をサーバーに実装して適切な操作を選択する必要があります。 このサンプルは、大文字と小文字を区別しない操作名のみを許可するように設定されています。

SelectOperation メソッドは、受信メッセージを受け取り、メッセージ のプロパティでVia URI を検索します。 URI から操作名サフィックスを抽出し、内部テーブルを検索してメッセージをディスパッチする操作名を取得し、その操作名を返します。

EnableHttpGetRequestsBehavior クラス

UriPathSuffixOperationSelector コンポーネントは、プログラムによって、またはエンドポイントの動作を使用して設定できます。 このサンプルでは、サービスのアプリケーション構成ファイルで指定されている EnableHttpGetRequestsBehavior 動作を実装します。

サーバーで次の手順を実行します。

OperationSelectorは、IDispatchOperationSelector実装に設定されます。

既定では、WCF では完全一致アドレス フィルターが使用されます。 受信メッセージの URI には、操作名サフィックスの後にパラメーター データを含むクエリ文字列が含まれているため、エンドポイントの動作によってアドレス フィルターもプレフィックス一致フィルターに変更されます。 この目的のために WCFPrefixEndpointAddressMessageFilter を使用します。

操作フォーマッタのインストール

フォーマッタを指定する操作の動作は一意です。 このような動作の 1 つは、必要な操作フォーマッタを作成するすべての操作に対して、常に既定で実装されます。 ただし、これらの動作は単なる別の操作動作のように見えます。他の属性では識別できません。 置換動作をインストールするには、既定で WCF 型ローダーによってインストールされる特定のフォーマッタ動作を検索し、それを置き換えるか、既定の動作の後に実行する互換性のある動作を追加する必要があります。

これらの操作フォーマッタの動作は、 CommunicationObject.Open を呼び出す前に、または既定の動作の後に実行される操作動作を指定することによって、プログラムによって設定できます。 ただし、動作モデルでは動作が他の動作を置き換えたり、説明ツリーを変更したりできないため、エンドポイントの動作 (したがって構成) によって簡単に設定することはできません。

クライアントで次の手順を実行します。

要求を HTTP GET 要求に変換し、応答用に元のフォーマッタに委任できるように、 IClientMessageFormatter 実装を実装する必要があります。 これを行うには、 EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior ヘルパー メソッドを呼び出します。

これは、 CreateChannelを呼び出す前に行う必要があります。

void ReplaceFormatterBehavior(OperationDescription operationDescription, EndpointAddress address)
{
    // Remove the DataContract behavior if it is present.
    IOperationBehavior formatterBehavior = operationDescription.Behaviors.Remove<DataContractSerializerOperationBehavior>();
    if (formatterBehavior == null)
    {
        // Remove the XmlSerializer behavior if it is present.
        formatterBehavior = operationDescription.Behaviors.Remove<XmlSerializerOperationBehavior>();
        ...
    }

    // Remember what the innerFormatterBehavior was.
    DelegatingFormatterBehavior delegatingFormatterBehavior = new DelegatingFormatterBehavior(address);
    delegatingFormatterBehavior.InnerFormatterBehavior = formatterBehavior;
   operationDescription.Behaviors.Add(delegatingFormatterBehavior);
}

サーバーで次の手順を実行します。

  • HTTP GET 要求を読み取り、応答を書き込むための元のフォーマッタに委任できるように、 IDispatchMessageFormatter インターフェイスを実装する必要があります。 これを行うには、クライアントと同じ EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior ヘルパー メソッドを呼び出します (前のコード サンプルを参照)。

  • これは、 Open が呼び出される前に行う必要があります。 このサンプルでは、 Openを呼び出す前にフォーマッタを手動で変更する方法を示します。 同じことを実現するもう 1 つの方法は、開く前にEnableHttpGetRequestsBehavior.ReplaceFormatterBehaviorの呼び出しを行うServiceHostからクラスを派生することです (例については、ホスティングのドキュメントとサンプルを参照してください)。

ユーザー エクスペリエンス

サーバーで次の手順を実行します。

  • サーバー ICalculator の実装を変更する必要はありません。

  • サービスの App.config では、textMessageEncoding要素のmessageVersion属性をNoneに設定するカスタム POX バインディングを使用する必要があります。

    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding messageVersion="None" />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
    
  • また、サービスの App.config では、カスタム EnableHttpGetRequestsBehavior を動作拡張セクションに追加して使用して指定する必要があります。

    <behaviors>
      <endpointBehaviors>
        <behavior name="enableHttpGetRequestsBehavior">
          <enableHttpGetRequests />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    
    <extensions>
      <behaviorExtensions>
        <!-- Enabling HTTP GET requests: Behavior Extension -->
        <add
          name="enableHttpGetRequests"           type="Microsoft.ServiceModel.Samples.EnableHttpGetRequestsBehaviorElement, QueryStringFormatter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
    
  • Openを呼び出す前に操作フォーマッタを追加します。

クライアントで次の手順を実行します。

  • クライアントの実装を変更する必要はありません。

  • クライアントの App.config は、textMessageEncoding要素のmessageVersion属性をNoneに設定するカスタム POX バインドを使用する必要があります。 サービスとの違いの 1 つは、送信先アドレスを変更できるように、クライアントが手動アドレス指定を有効にする必要があるということです。

    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding messageVersion="None" />
          <httpTransport manualAddressing="True" />
        </binding>
      </customBinding>
    </bindings>
    
  • クライアントの App.config は、サーバーと同じカスタム EnableHttpGetRequestsBehavior を指定する必要があります。

  • CreateChannel()を呼び出す前に操作フォーマッタを追加します。

サンプルを実行すると、操作要求と応答がクライアント コンソール ウィンドウに表示されます。 4 つの演算 (加算、減算、乗算、除算) はすべて成功する必要があります。

サンプルを設定、ビルド、実行するには
  1. Windows Communication Foundation サンプル One-Time セットアップ手順を実行していることを確認します。

  2. ソリューションをビルドするには、「 Windows Communication Foundation サンプルのビルド」の手順に従います。

  3. 単一または複数のコンピューター間の構成でサンプルを実行するには、「Windows Communication Foundation Samplesの実行」の手順に従います。