Filtro de Mensagens Personalizado

O exemplo MessageFilter demonstra como substituir os filtros de mensagem que o Windows Communication Foundation (WCF) usa para enviar mensagens para pontos de extremidade.

Nota

O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.

Quando a primeira mensagem em um canal chega ao servidor, o servidor deve determinar qual (se houver) dos pontos de extremidade associados a esse URI deve receber a mensagem. Esse processo é controlado pelos MessageFilter objetos anexados ao EndpointDispatcher.

Cada ponto de extremidade de um serviço tem um único EndpointDispatcher. O EndpointDispatcher tem um AddressFilter e um ContractFilter. A união desses dois filtros é o filtro de mensagem usado para esse ponto de extremidade.

Por padrão, o AddressFilter para um ponto de extremidade corresponde a qualquer mensagem endereçada a um endereço que corresponda ao ponto de EndpointAddressextremidade do serviço. Por padrão, o ContractFilter para um ponto de extremidade inspeciona a ação da mensagem de entrada e faz a correspondência de qualquer mensagem com uma ação que corresponde a uma das ações das operações do contrato de ponto de extremidade de serviço (apenas IsInitiating=true as ações são consideradas). Como resultado, por padrão, o filtro de um ponto de extremidade só corresponde se o cabeçalho Para da mensagem for o EndpointAddress do ponto de extremidade e a ação da mensagem corresponder a uma das ações da operação do ponto de extremidade.

Esses filtros podem ser alterados usando um comportamento. No exemplo, o serviço cria um IEndpointBehavior que substitui o AddressFilter e ContractFilter no EndpointDispatcher:

class FilteringEndpointBehavior : IEndpointBehavior
{
    //...
}

Dois filtros de endereço são definidos:

// 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 { }

O FilteringEndpointBehavior é feito configurável e permite duas variações diferentes.

public class FilteringEndpointBehaviorExtension : BehaviorExtensionElement { }

A Variação 1 corresponde apenas aos endereços que contêm um 'e' (mas que têm qualquer Ação), enquanto a Variação 2 corresponde apenas aos endereços que não têm um 'e':

if (Variation == 1)
    return new FilteringEndpointBehavior(
        new MatchEAddressFilter(), new MatchAllMessageFilter());
else
    return new FilteringEndpointBehavior(
        new MatchNoEAddressFilter(), new MatchAllMessageFilter());

No arquivo de configuração, o serviço registra o novo comportamento:

<extensions>
    <behaviorExtensions>
        <add name="filteringEndpointBehavior" type="Microsoft.ServiceModel.Samples.FilteringEndpointBehaviorExtension, service" />
    </behaviorExtensions>
</extensions>

Em seguida, o serviço cria endpointBehavior configurações para cada variação:

<endpointBehaviors>
    <behavior name="endpoint1">
        <filteringEndpointBehavior variation="1" />
    </behavior>
    <behavior name="endpoint2">
        <filteringEndpointBehavior variation="2" />
    </behavior>
</endpointBehaviors>

Finalmente, o ponto de extremidade do serviço faz referência a um dos behaviorConfigurationsseguintes:

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

A implementação da aplicação cliente é simples; ele cria dois canais para o URI do serviço (passando esse valor como o segundo parâmetro (via) para CreateChannel(EndpointAddress) e envia uma única mensagem em cada canal, mas usa endereços de ponto de extremidade diferentes para cada um. Como resultado, as mensagens de saída do cliente têm designações To diferentes, e o servidor responde de acordo, conforme demonstrado pela saída do cliente:

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

Alternar a variação no arquivo de configuração do servidor faz com que o filtro seja trocado e o cliente vê o comportamento oposto (a mensagem para urn:e ter êxito, enquanto a mensagem para urn:a falhar).

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

Para configurar, compilar e executar o exemplo

  1. Para criar a solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

  2. Para executar o exemplo em uma configuração de máquina única, siga as instruções em Executando os exemplos do Windows Communication Foundation.

  3. Para executar o exemplo em uma configuração entre máquinas, siga as instruções em Executando os exemplos do Windows Communication Foundation e altere a seguinte linha no Client.cs.

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

    Substitua localhost pelo nome do servidor.

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