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


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.

Настройка, сборка и выполнение образца

  1. Установите ASP.NET 4.0 с помощью следующей команды.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Убедитесь, что вы выполнили процедуру однократной установки для примеров Windows Communication Foundation.

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

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