自定义消息筛选器

本示例演示如何替换 Windows Communication Foundation (WCF) 用于将消息调度到终结点的消息筛选器。

Aa717046.note(zh-cn,VS.100).gif注意:
本主题的最后介绍了此示例的设置过程和生成说明。

当通道上的第一个消息到达服务器时,服务器必须确定哪个(如果有)与该 URI 关联的终结点应该接收消息。此过程受附加到 EndpointDispatcherMessageFilter 对象控制。

服务的每个终结点都有一个 EndpointDispatcherEndpointDispatcher 同时具有 AddressFilterContractFilter。这两个筛选器的联合是用于该终结点的消息筛选器。

默认情况下,终结点的 AddressFilter 与发送到某个地址的任何消息匹配,该地址与服务终结点的 EndpointAddress 的匹配。默认情况下,终结点的 ContractFilter 检查传入消息的操作并匹配任何具有某一操作的消息(该操作对应于服务终结点协定的操作之一)(只考虑 IsInitiating=true 的操作)。因此,默认情况下,仅当消息的 To 标头为终结点的 EndpointAddress 并且消息的动作与终结点操作的动作之一匹配时,终结点的筛选器才与此消息匹配。

使用行为可以更改这些筛选器。在本示例中,服务创建一个 IEndpointBehavior,该行为替换 EndpointDispatcher 上的 AddressFilterContractFilter

class FilteringEndpointBehavior : IEndpointBehavior …

定义两个地址筛选器:

// 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 变得可配置并允许两个不同变体。

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 之一:

<endpoint address=""
        bindingConfiguration="ws"
        listenUri="" 
        binding="wsHttpBinding"
        contract="Microsoft.ServiceModel.Samples.IHello" 
        behaviorConfiguration="endpoint2" />

客户端应用程序的实现非常简单;它通过将该值作为到 CreateChannel 的第二个 (via) 参数传入并在每个通道上发送单个消息,但分别使用不同的终结点地址,创建两个到达服务的 URI 的通道。因此,来自客户端的出站消息具有不同的 To 标记,服务器做出相应响应,如客户端的输出所示:

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" />
Aa717046.Important(zh-cn,VS.100).gif 注意:
您的计算机上可能已安装这些示例。在继续操作之前,请先检查以下(默认)目录。

<安装驱动器>:\WF_WCF_Samples

如果此目录不存在,请访问针对 .NET Framework 4 的 Windows Communication Foundation (WCF) 和 Windows Workflow Foundation (WF) 示例(可能为英文网页),下载所有 Windows Communication Foundation (WCF) 和 WF 示例。此示例位于以下目录。

<安装驱动器>:\WF_WCF_Samples\WCF\Extensibility\MessageFilter

设置、生成和运行示例

  1. 若要生成解决方案,请按照生成 Windows Communication Foundation 示例中的说明进行操作。

  2. 若要用单一计算机配置运行此示例,请按照Running the Windows Communication Foundation Samples中的说明进行操作。

  3. 若要用跨计算机配置来运行示例,请按照Running the Windows Communication Foundation Samples中的说明进行操作并更改 Client.cs 中的以下行。

    Uri serviceVia = new Uri("https://localhost/ServiceModelSamples/service.svc");
    

    用服务器的名称替换 localhost。

    Uri serviceVia = new Uri("http://servermachinename/ServiceModelSamples/service.svc");