HttpCookieSession
В этом образце показано, как построить пользовательский канал протокола, который использует для управления сеансами протокол HTTP. Этот канал обеспечивает взаимодействие между службами Windows Communication Foundation (WCF) и клиентами ASMX или между клиентами WCF и службами ASMX.
Когда клиент вызывает веб-метод в основанной на сеансах веб-службе ASMX, система ASP.NET выполняет следующие операции:
создает уникальный идентификатор сеанса;
создает объект сеанса и связывает его с уникальным идентификатором;
добавляет уникальный идентификатор в заголовок HTTP-ответа Set-Cookie и отправляет его клиенту;
определяет клиент в последующих вызовах по идентификатору сеанса и использует его для отправки сообщений.
Клиент включает этот идентификатор сеанса во все дальнейшие запросы к серверу. Сервер использует идентификатор сеанса клиента, чтобы загружать соответствующий объект сеанса для текущего контекста HTTP.
Примечание |
---|
Образцы уже могут быть установлены на компьютере. Перед продолжением проверьте следующий каталог (по умолчанию).
<диск_установки>:\WF_WCF_Samples
Если этот каталог не существует, перейдите на страницу Образцы Windows Communication Foundation (WCF) и Windows Workflow Foundation (WF) для .NET Framework 4, чтобы загрузить все образцы Windows Communication Foundation (WCF) и WF. Этот образец расположен в следующем каталоге.
<диск_установки>:\WF_WCF_Samples\WCF\Extensibility\Channels\HttpCookieSession
|
Шаблон обмена сообщениями канала 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 if (this.completeReceiveCallback == null) { 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="https://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="https://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
— это элемент BindingElementExtensionElement, который предоставляет элемент HttpCookieSessionBindingElement
системе конфигурации. С помощью нескольких простых переопределений определяется имя раздела конфигурации, тип элемента привязки и способ создания элемента привязки. Мы можем затем зарегистрировать раздел расширения в файле конфигурации следующим образом.
<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.
Чтобы выполнить образец на одном или нескольких компьютерах, следуйте инструкциям раздела Running the Windows Communication Foundation Samples.