Пользовательский фильтр сообщений
В примере 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" />
Настройка, сборка и выполнение образца
Чтобы создать решение, следуйте инструкциям по созданию примеров 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");