Поделиться через


Пользовательский фильтр сообщений

В примере MessageFilter показано, как заменить фильтры сообщений, которые Windows Communication Foundation (WCF) использует для отправки сообщений в конечные точки.

Замечание

Процедура установки и инструкции по сборке для этого примера находятся в конце этого раздела.

Когда первое сообщение на канале поступает на сервер, сервер должен определить, какие (если есть) конечных точек, связанных с этим URI, должны получать сообщение. Этот процесс управляется объектами, MessageFilter подключенными к объекту EndpointDispatcher.

Каждая конечная точка сервиса имеет одну EndpointDispatcher. У EndpointDispatcher есть и AddressFilter, и ContractFilter. Объединение этих двух фильтров — это фильтр сообщений, используемый для этой конечной точки.

По умолчанию AddressFilter для конечной точки соответствует любому сообщению, адресуемому на адрес, который соответствует EndpointAddress конечной точке службы. По умолчанию ContractFilter, конечная точка проверяет действие входящего сообщения и сопоставляет любое сообщение с действием, которому соответствует одно из действий операций контракта конечной точки обслуживания (учитываются только IsInitiating=true действия). В результате по умолчанию фильтр для конечной точки совпадает только в том случае, если заголовок сообщения To является EndpointAddress конечной точкой, а действие сообщения соответствует одному из действий операции конечной точки.

Эти фильтры можно изменить с помощью поведения. В примере служба создает объект IEndpointBehavior, который заменяет AddressFilter и ContractFilter на EndpointDispatcher.

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" />

Реализация клиентского приложения проста; он создает два канала в URI службы (передавая это значение в качестве второго (via) параметра CreateChannel(EndpointAddress) и отправляя одно сообщение на каждый канал, но использует разные адреса конечных точек для каждого канала. В результате исходящие сообщения от клиента имеют разные обозначения 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" />

Настройка, сборка и запуск примера

  1. Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.

  2. Чтобы запустить пример в конфигурации с одним компьютером, следуйте инструкциям в разделе "Примеры Windows Communication Foundation".

  3. Чтобы запустить пример в конфигурации между компьютерами, следуйте инструкциям в разделе "Запуск примеров Windows Communication Foundation" и измените следующую строку в Client.cs.

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

    Замените localhost именем сервера.

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