Compartir a través de


Filtro de mensajes personalizado

En el ejemplo MessageFilter se muestra cómo reemplazar los filtros de mensaje que Windows Communication Foundation (WCF) usa para enviar mensajes a los puntos de conexión.

Nota:

El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.

Cuando el primer mensaje de un canal llega al servidor, el servidor debe determinar cuáles (si los hay) de los puntos de conexión asociados a ese URI deben recibir el mensaje. Este proceso se controla mediante los MessageFilter objetos adjuntos a EndpointDispatcher.

Cada extremo de un servicio tiene un EndpointDispatcherúnico. El EndpointDispatcher tiene tanto un AddressFilter como un ContractFilter. La unión de estos dos filtros es el filtro de mensajes que se usa para ese punto de conexión.

De forma predeterminada, el AddressFilter de un punto de conexión coincide con cualquier mensaje dirigido a una dirección que coincida con el EndpointAddress del punto de conexión de servicio. De forma predeterminada, el ContractFilter de un punto de conexión inspecciona la acción del mensaje entrante y coincide con cualquier mensaje cuya acción corresponda a una de las acciones de las operaciones del contrato del punto de conexión del servicio (solo se consideran las acciones IsInitiating=true). Como resultado, de forma predeterminada, el filtro para un punto de conexión coincide solo si el encabezado del mensaje Para es EndpointAddress del punto de conexión y la acción del mensaje coincide con una de las acciones de la operación del punto de conexión.

Estos filtros se pueden cambiar mediante un comportamiento. En el ejemplo, el servicio crea un objeto IEndpointBehavior que reemplaza AddressFilter y ContractFilter en el EndpointDispatcher:

class FilteringEndpointBehavior : IEndpointBehavior
{
    //...
}

Se definen dos filtros de dirección:

// 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 se configura y permite dos variaciones diferentes.

public class FilteringEndpointBehaviorExtension : BehaviorExtensionElement { }

La variación 1 solo coincide con las direcciones que contienen un "e" (pero que tienen cualquier acción), mientras que la variación 2 coincide solo con las direcciones que carecen de una "e":

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

En el archivo de configuración, el servicio registra el nuevo comportamiento:

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

A continuación, el servicio crea endpointBehavior configuraciones para cada variación:

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

Por último, el punto de conexión del servicio hace referencia a uno de los behaviorConfigurationselementos :

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

La implementación de la aplicación cliente es sencilla; crea dos canales al URI del servicio (pasando ese valor como segundo parámetro (via) a CreateChannel(EndpointAddress) y envía un único mensaje en cada canal, pero usa direcciones de punto de conexión diferentes para cada uno. Como resultado, los mensajes salientes del cliente tienen diferentes designaciones de To y el servidor responde en consecuencia, como se muestra en la salida del 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

Al cambiar la variación en el archivo de configuración del servidor, el filtro se intercambia y el cliente experimenta el comportamiento opuesto (el mensaje a urn:e tiene éxito, mientras que falla el mensaje a urn:a).

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

Para configurar, compilar y ejecutar el ejemplo

  1. Para compilar la solución, siga las instrucciones que se indican en Compilación de los ejemplos de Windows Communication Foundation.

  2. Para ejecutar el ejemplo en una configuración de una sola máquina, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.

  3. Para ejecutar el ejemplo en una configuración entre máquinas, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation y cambie la siguiente línea en Client.cs.

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

    Reemplace localhost por el nombre del servidor.

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