カスタム メッセージ フィルター
MessageFilter サンプルでは、Windows Communication Foundation (WCF) でメッセージをエンドポイントにディスパッチするために使用されるメッセージ フィルターを置き換える方法を示します。
Note
このサンプルのセットアップ手順とビルド手順については、このトピックの最後を参照してください。
チャネルでの最初のメッセージがサーバーに到着すると、サーバーは、URI に関連付けられているエンドポイントがある場合に、どのエンドポイントがメッセージを受信する必要があるかを判断する必要があります。 この処理は、MessageFilter に関連付けられている EndpointDispatcher オブジェクトで制御されます。
サービスの各エンドポイントには、単一の EndpointDispatcher があります。 EndpointDispatcher には、AddressFilter と ContractFilter の両方があります。 これら 2 つのフィルタを結合したものが、このエンドポイントに使用されるメッセージ フィルタです。
エンドポイントの AddressFilter の既定では、アドレス指定されているメッセージと、サービス エンドポイントの EndpointAddress に一致するアドレスを照合します。 既定では、エンドポイントの ContractFilter では、受信メッセージのアクションを検査し、サービス エンドポイント コントラクトの操作のいずれかのアクション (対象になるのは IsInitiating
=true
のアクションのみ) に対応するアクションが含まれるメッセージを照合します。 その結果、エンドポイントのフィルタの既定で一致と見なされるのは、メッセージの To ヘッダーがエンドポイントの EndpointAddress に一致し、メッセージのアクションがエンドポイントの操作のいずれかのアクションと一致するという、2 つの条件がどちらも満たされる場合だけです。
これらのフィルタは、動作を使用して変更できます。 サンプルのサービスは、次のように IEndpointBehavior を作成して、AddressFilter の ContractFilter と EndpointDispatcher を置き換えます。
class FilteringEndpointBehavior : IEndpointBehavior
{
//...
}
2 つのアドレス フィルタは、次のように定義されます。
// Matches any message whose To address contains the letter 'e'
class MatchEAddressFilter : MessageFilter { }
// Matches any message whose To address does not contain the letter 'e'
class MatchNoEAddressFilter : MessageFilter { }
FilteringEndpointBehavior
は構成可能になり、2 つの異なるバリエーションを設定できます。
public class FilteringEndpointBehaviorExtension : BehaviorExtensionElement { }
バリエーション 1 では 'e' が含まれる (ただし任意のアクションを含む) アドレスのみを照合します。これに対して、バリエーション 2 では 'e' が含まれないアドレスのみを照合します。
if (Variation == 1)
return new FilteringEndpointBehavior(
new MatchEAddressFilter(), new MatchAllMessageFilter());
else
return new FilteringEndpointBehavior(
new MatchNoEAddressFilter(), new MatchAllMessageFilter());
構成ファイルでは、サービスは次のように新しい動作を登録します。
<extensions>
<behaviorExtensions>
<add name="filteringEndpointBehavior" type="Microsoft.ServiceModel.Samples.FilteringEndpointBehaviorExtension, service" />
</behaviorExtensions>
</extensions>
次に、各バリエーションの endpointBehavior
構成を次のように作成します。
<endpointBehaviors>
<behavior name="endpoint1">
<filteringEndpointBehavior variation="1" />
</behavior>
<behavior name="endpoint2">
<filteringEndpointBehavior variation="2" />
</behavior>
</endpointBehaviors>
最後に、サービスのエンドポイントは、behaviorConfigurations
の 1 つを次のように参照します。
<endpoint address=""
bindingConfiguration="ws"
listenUri=""
binding="wsHttpBinding"
contract="Microsoft.ServiceModel.Samples.IHello"
behaviorConfiguration="endpoint2" />
クライアント アプリケーションの実装は単純で、URI の値を 2 番目の (via
) パラメータとして CreateChannel(EndpointAddress) に渡すことによって、2 つのチャネルをサービスの URI に作成し、各チャネルに 1 つのメッセージを送信します。ただし、チャネルごとに異なるエンドポイント アドレスが使用されます。 この結果、次のクライアントの出力に示すように、クライアントからの送信メッセージにはそれぞれ異なる宛先が指定され、サーバーはこれに応じて応答します。
Sending message to urn:e...
Exception: The message with To 'urn:e' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.
Sending message to urn:a...
Hello
サーバーの構成ファイルのバリエーションを切り替えると、フィルターが入れ替わり、クライアントには逆の動作が表示されます (urn:e
へのメッセージは正常に送信されますが、urn:a
へのメッセージはエラーになります)。
<endpoint address=""
bindingConfiguration="ws"
listenUri=""
binding="wsHttpBinding"
contract="Microsoft.ServiceModel.Samples.IHello"
behaviorConfiguration="endpoint1" />
サンプルをセットアップ、ビルド、および実行するには
ソリューションをビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。
単一コンピューター構成でサンプルを実行するには、「Windows Communication Foundation サンプルの実行」の手順に従います。
複数コンピューター構成でサンプルを実行するには、「Windows Communication Foundation サンプルの実行」の手順に従い、Client.cs の次の行を変更します。
Uri serviceVia = new Uri("http://localhost/ServiceModelSamples/service.svc");
つまり、localhost をサーバー名に置き換えます。
Uri serviceVia = new Uri("http://servermachinename/ServiceModelSamples/service.svc");