次の方法で共有


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

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

このサンプルは、ICalculator サービス コントラクトを実装する「入門サンプル」に基づいています。 加算、減算、乗算、および除算のメッセージを変更して、クライアントからサーバーへの要求を行うための HTTP GET と、サーバーからクライアントへの要求を行うための POX メッセージ付きの HTTP POST を使用する方法を示します。

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

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

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

  • EnableHttpGetRequestsBehavior エンドポイント動作 (および対応する構成)。必要な操作セレクタをランタイムに追加します。

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

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

Note

このサンプルのセットアップ手順とビルド手順については、このトピックの最後を参照してください。

主要概念

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

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

要求:

  • このサンプルでは、TypeConverter クラスを使用して要求メッセージ内のパラメータ データを文字列に変換したり、その逆の処理を行ったりします。 TypeConverter が特定の型で使用できない場合は、サンプルのフォーマッタから例外がスローされます。

  • クライアントの IClientMessageFormatter.SerializeRequest メソッドでは、フォーマッタは適切な宛先アドレスを使用して 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 の動作を実装します。

サーバー側 :

OperationSelectorIDispatchOperationSelector 実装に設定されます。

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

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

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

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

クライアント側 :

IClientMessageFormatter の実装を行って、要求を HTTP GET 要求に変換し、応答を元のフォーマッタに代行させる必要があります。 これを行うには、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);
}

サーバー側 :

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

  • この手順は、Open を呼び出す前に行う必要があります。 このサンプルでは、Open を呼び出す前にこのフォーマッタを手動で変更する方法を示します。 同じ結果を得るための別の方法としては、オープン操作の前に ServiceHost を呼び出す EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior からクラスを派生します (ホスティングのドキュメントおよびサンプル例を参照してください)。

ユーザー側の表示と操作

サーバー側 :

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

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

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

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

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

サンプルをセットアップ、ビルド、および実行するには
  1. Windows Communication Foundation サンプルの 1 回限りのセットアップの手順を実行したことを確認します。

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

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