HttpCookieSession
В примере HttpCookieSession показано, как создать пользовательский канал протокола для использования HTTP-файлов cookie для управления сеансами. Этот канал обеспечивает обмен данными между службами Windows Communication Foundation (WCF) и клиентами ASMX или между клиентами WCF и службами ASMX.
Когда клиент вызывает веб-метод в веб-службе ASMX, основанной на сеансе, подсистема ASP.NET выполняет следующие действия:
создает уникальный идентификатор сеанса;
создает объект сеанса и связывает его с уникальным идентификатором;
добавляет уникальный идентификатор в заголовок HTTP-ответа Set-Cookie и отправляет его клиенту;
определяет клиент в последующих вызовах по идентификатору сеанса и использует его для отправки сообщений.
Клиент включает этот идентификатор сеанса во все дальнейшие запросы к серверу. Сервер использует идентификатор сеанса клиента, чтобы загружать соответствующий объект сеанса для текущего контекста HTTP.
Шаблон обмена сообщениями канала HttpCookieSession
В этом примере включаются сеансы для сценариев, подобных применению служб ASMX. В нижней части стека каналов имеется транспорт HTTP, который поддерживает IRequestChannel и IReplyChannel. Именно канал отвечает за то, чтобы предоставлять сеансы каналам стека более высокого уровня. В образце реализуются два канала (IRequestSessionChannel и IReplySessionChannel), поддерживающих сеансы.
Канал службы
В этом образце создается канал службы в классе HttpCookieReplySessionChannelListener
. Этот класс реализует интерфейс IChannelListener и преобразует канал IReplyChannel из нижнего канала в стеке в канал IReplySessionChannel. Этот процесс можно разбить на следующие части.
Когда открывается прослушиватель канала, он принимает от своего внутреннего прослушивателя внутренний канал. Поскольку внутренний прослушиватель является прослушивателем датаграмм, а время существования принятого канала вычитается из времени существования прослушивателя, можно закрыть внутренний прослушиватель и работать только с внутренним каналом.
this.innerChannelListener.Open(timeoutHelper.RemainingTime()); this.innerChannel = this.innerChannelListener.AcceptChannel(timeoutHelper.RemainingTime()); this.innerChannel.Open(timeoutHelper.RemainingTime()); this.innerChannelListener.Close(timeoutHelper.RemainingTime());
После завершения процесса открытия мы настраиваем цикл сообщений, чтобы получать сообщения от внутреннего канала.
IAsyncResult result = BeginInnerReceiveRequest(); if (result != null && result.CompletedSynchronously) { // do not block the user thread this.completeReceiveCallback ??= new WaitCallback(CompleteReceiveCallback); ThreadPool.QueueUserWorkItem(this.completeReceiveCallback, result); }
Когда сообщение прибывает, канал службы проверяет идентификатор сеанса и демультиплексирует его в соответствующий канал сеанса. Прослушиватель канала поддерживает словарь, который сопоставляет идентификаторы сеансов с экземплярами каналов сеансов.
Dictionary<string, IReplySessionChannel> channelMapping;
Класс HttpCookieReplySessionChannel
реализует IReplySessionChannel. Более высокие уровня стека каналов вызывают метод ReceiveRequest для чтения запросов для этого сеанса. У каждого канала сеанса имеется закрытая очередь сообщений, заполняемая каналом службы.
InputQueue<RequestContext> requestQueue;
Если происходит вызов метода ReceiveRequest, а в очереди сообщений нет сообщений, то канал ждет в течение заданного времени, а затем отключается. Это очищает каналы сеансов, созданные для клиентов, отличных от WCF.
Мы используем channelMapping
для отслеживания ReplySessionChannels
и не закрываем соответствующий канал innerChannel
, пока не будут закрыты все принятые каналы. Таким образом, канал HttpCookieReplySessionChannel
может существовать после истечения времени существования HttpCookieReplySessionChannelListener
. Кроме того, нам не нужно беспокоиться о попадании прослушивателя под сборку мусора, поскольку принятые каналы сохраняют ссылку на свой прослушиватель с помощью обратного вызова OnClosed
.
Клиентский канал
Соответствующий клиентский канал создается в классе HttpCookieSessionChannelFactory
. Во время создания канал фабрика каналов с помощью HttpCookieRequestSessionChannel
создает оболочку для внутреннего канала запросов. Класс HttpCookieRequestSessionChannel
перенаправляет вызовы в соответствующий канал запросов. Когда клиент закрывает прокси, HttpCookieRequestSessionChannel
отправляет службе сообщение о том, что канал закрывается. Таким образом, стек каналов службы может безопасно закрыть используемый канал сеанса.
Привязка и элемент привязки
После создания каналов службы и клиента необходимо интегрировать их в среду выполнения WCF. Каналы предоставляются WCF через привязки и элементы привязки. Привязка состоит из одного или нескольких элементов привязки. WCF предлагает несколько системных привязок; Например, BasicHttpBinding или WSHttpBinding. Класс HttpCookieSessionBindingElement
содержит реализацию элемента привязки. Он переопределяет прослушиватель канала и методы создания фабрики канала для создания нужных экземпляров прослушивателя канала и фабрики каналов.
В этом образце для описания службы используются утверждения политики. Это позволяет образцу публиковать свои требования к каналам для других клиентов, которые могут пользоваться службой. Например, этот элемент привязки публикует утверждения политики, позволяющие потенциальным клиентам узнать, служба поддерживает сеансы. Поскольку в конфигурации элемента привязки этого образца включено свойство ExchangeTerminateMessage
, оно добавляет необходимые утверждения, чтобы показать, что служба поддерживает дополнительные действия обмена сообщениями для завершения сеанса. Клиенты могут использовать это действие. В следующем коде WSDL показаны утверждения политики, созданные на базе элемента HttpCookieSessionBindingElement
.
<wsp:Policy wsu:Id="HttpCookieSessionBinding_IWcfCookieSessionService_policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<wspe:Utf816FFFECharacterEncoding xmlns:wspe="http://schemas.xmlsoap.org/ws/2004/09/policy/encoding"/>
<mhsc:httpSessionCookie xmlns:mhsc="http://samples.microsoft.com/wcf/mhsc/policy"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Класс HttpCookieSessionBinding
является предоставляемой системой привязкой, которая использует описанный выше элемент привязки.
Добавление канала в систему конфигурации
В этом образце имеется два канала, делающие канал доступным через конфигурацию. Первый - элемент BindingElementExtensionElement для HttpCookieSessionBindingElement
. Основная часть реализации делегируется классу HttpCookieSessionBindingConfigurationElement
, наследуемому от класса StandardBindingElement. Элемент HttpCookieSessionBindingConfigurationElement
имеет свойства, которые соответствуют свойствам элемента HttpCookieSessionBindingElement
.
Раздел расширения элемента привязки
Этот раздел HttpCookieSessionBindingElementSection
представляет BindingElementExtensionElementHttpCookieSessionBindingElement
собой доступ к системе конфигурации. С помощью нескольких простых переопределений определяется имя раздела конфигурации, тип элемента привязки и способ создания элемента привязки. Мы можем затем зарегистрировать раздел расширения в файле конфигурации следующим образом.
<configuration>
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="httpCookieSession"
type=
"Microsoft.ServiceModel.Samples.HttpCookieSessionBindingElementElement,
HttpCookieSessionExtension, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null"/>
</bindingElementExtensions >
</extensions>
<bindings>
<customBinding>
<binding name="allowCookiesBinding">
<textMessageEncoding messageVersion="Soap11WSAddressing10" />
<httpCookieSession sessionTimeout="10" exchangeTerminateMessage="true" />
<httpTransport allowCookies="true" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
Тестовый код
Тестовый код для использования этого примера транспорта находится в каталогах Client и Service. Он состоит из двух тестов— один тест использует привязку с allowCookies
установленным значением true
на клиенте. Второй тест включает на привязке явное отключение (с помощью обмена сообщениями завершения).
При запуске примера результат должен выглядеть следующим образом:
Simple binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3
Smart binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3
Press <ENTER> to terminate client.
Настройка, сборка и выполнение образца
Установите ASP.NET 4.0 с помощью следующей команды.
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
Убедитесь, что вы выполнили процедуру однократной установки для примеров Windows Communication Foundation.
Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.
Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в разделе "Примеры Windows Communication Foundation".