HttpCookieSession

O exemplo HttpCookieSession demonstra como criar um canal de protocolo personalizado para usar cookies HTTP para gerenciamento de sessão. Esse canal permite a comunicação entre serviços do Windows Communication Foundation (WCF) e clientes ASMX ou entre clientes WCF e serviços ASMX.

Quando um cliente chama um método Web em um serviço Web ASMX baseado em sessão, o mecanismo de ASP.NET faz o seguinte:

  • Gera um ID exclusivo (ID de sessão).

  • Gera o objeto de sessão e o associa à ID exclusiva.

  • Adiciona a ID exclusiva a um cabeçalho de resposta HTTP Set-Cookie e a envia para o cliente.

  • Identifica o cliente em chamadas subsequentes com base no ID de sessão que ele envia a ele.

O cliente inclui esse ID de sessão em suas solicitações subsequentes ao servidor. O servidor usa o ID de sessão do cliente para carregar o objeto de sessão apropriado para o contexto HTTP atual.

Padrão de troca de mensagens do canal HttpCookieSession

Este exemplo permite sessões para cenários semelhantes ao ASMX. Na parte inferior da nossa pilha de canais, temos o transporte HTTP que suporta IRequestChannel e IReplyChannel. É o trabalho do canal para fornecer sessões para os níveis mais altos da pilha de canais. O exemplo implementa dois canais, (IRequestSessionChannel e IReplySessionChannel) que suportam sessões.

Canal de Atendimento

O exemplo fornece um canal de serviço na HttpCookieReplySessionChannelListener classe. Esta classe implementa a IChannelListener interface e converte o IReplyChannel canal de baixo na pilha de canais para um IReplySessionChannel. Este processo pode ser dividido nas seguintes partes:

  • Quando o ouvinte do canal é aberto, ele aceita um canal interno de seu ouvinte interno. Como o ouvinte interno é um ouvinte de datagrama e o tempo de vida de um canal aceito é dissociado do tempo de vida do ouvinte, podemos fechar o ouvinte interno e apenas manter o canal interno

                this.innerChannelListener.Open(timeoutHelper.RemainingTime());
    this.innerChannel = this.innerChannelListener.AcceptChannel(timeoutHelper.RemainingTime());
    this.innerChannel.Open(timeoutHelper.RemainingTime());
    this.innerChannelListener.Close(timeoutHelper.RemainingTime());
    
  • Quando o processo aberto for concluído, configuramos um loop de mensagens para receber mensagens do canal interno.

    IAsyncResult result = BeginInnerReceiveRequest();
    if (result != null && result.CompletedSynchronously)
    {
       // do not block the user thread
       this.completeReceiveCallback ??= new WaitCallback(CompleteReceiveCallback);
       ThreadPool.QueueUserWorkItem(this.completeReceiveCallback, result);
    }
    
  • Quando uma mensagem chega, o canal de serviço examina o identificador de sessão e elimina os multiplexes para o canal de sessão apropriado. O ouvinte do canal mantém um dicionário que mapeia os identificadores de sessão para as instâncias do canal de sessão.

    Dictionary<string, IReplySessionChannel> channelMapping;
    

A HttpCookieReplySessionChannel classe implementa IReplySessionChannel. Níveis mais altos da pilha de canais chamam o ReceiveRequest método para ler solicitações para esta sessão. Cada canal de sessão tem uma fila de mensagens privadas que é preenchida pelo canal de serviço.

InputQueue<RequestContext> requestQueue;

No caso em que alguém chama o ReceiveRequest método e não há mensagens na fila de mensagens, o canal aguarda por um período de tempo especificado antes de se desligar. Isso limpa os canais de sessão criados para clientes não-WCF.

Usamos o channelMapping para rastrear o ReplySessionChannels, e não fechamos nosso subjacente innerChannel até que todos os canais aceitos tenham sido fechados. Esta forma HttpCookieReplySessionChannel pode existir para além da vida útil do HttpCookieReplySessionChannelListener. Também não temos que nos preocupar com o ouvinte recebendo lixo coletado embaixo de nós, porque os canais aceitos mantêm uma referência ao seu ouvinte através do retorno de OnClosed chamada.

Canal do cliente

O canal de HttpCookieSessionChannelFactory cliente correspondente está na classe. Durante a criação do canal, a fábrica de canais envolve o canal de solicitação interno com um HttpCookieRequestSessionChannelarquivo . A HttpCookieRequestSessionChannel classe encaminha as chamadas para o canal de solicitação subjacente. Quando o cliente fecha o proxy, HttpCookieRequestSessionChannel envia uma mensagem para o serviço que indica que o canal está sendo fechado. Assim, a pilha de canais de serviço pode desligar graciosamente o canal de sessão que está em uso.

Elemento de vinculação e vinculação

Depois de criar os canais de serviço e cliente, a próxima etapa é integrá-los ao tempo de execução do WCF. Os canais são expostos ao WCF por meio de ligações e elementos de ligação. Uma ligação consiste em um ou vários elementos de ligação. O WCF oferece várias ligações definidas pelo sistema; por exemplo, BasicHttpBinding ou WSHttpBinding. A HttpCookieSessionBindingElement classe contém a implementação para o elemento de ligação. Ele substitui o ouvinte de canal e os métodos de criação de fábrica de canal para fazer o ouvinte de canal necessário ou instanciações de fábrica de canal.

O exemplo usa asserções de política para a descrição do serviço. Isso permite que o exemplo publique seus requisitos de canal para outros clientes que podem consumir o serviço. Por exemplo, esse elemento de vinculação publica asserções de política para informar aos clientes em potencial que ele oferece suporte a sessões. Como o exemplo habilita a ExchangeTerminateMessage propriedade na configuração do elemento de ligação, ele adiciona as asserções necessárias para mostrar que o serviço oferece suporte a uma ação extra de troca de mensagens para encerrar a conversa da sessão. Os clientes podem usar essa ação. O código WSDL a seguir mostra as asserções de política criadas a HttpCookieSessionBindingElementpartir do .

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

A HttpCookieSessionBinding classe é uma associação fornecida pelo sistema que usa o elemento binding descrito anteriormente.

Adicionando o canal ao sistema de configuração

O exemplo fornece duas classes que expõem o canal de exemplo através da configuração. O primeiro é um BindingElementExtensionElement para o HttpCookieSessionBindingElement. A maior parte da implementação é delegada ao , que deriva HttpCookieSessionBindingConfigurationElementde StandardBindingElement. O HttpCookieSessionBindingConfigurationElement tem propriedades que correspondem às propriedades em HttpCookieSessionBindingElement.

Seção de extensão de elemento de vinculação

A seção HttpCookieSessionBindingElementSection é uma BindingElementExtensionElement que expõe HttpCookieSessionBindingElement ao sistema de configuração. Com algumas substituições, o nome da seção de configuração, o tipo do elemento de vinculação e como criar o elemento de vinculação são definidos. Podemos então registrar a seção de extensão em um arquivo de configuração da seguinte maneira:

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

Código de teste

O código de teste para usar esse transporte de exemplo está disponível nos diretórios Cliente e Serviço. Ele consiste em dois testes — um teste usa uma ligação com allowCookies set to true no cliente. O segundo teste permite o desligamento explícito (usando a troca de mensagens terminate) na ligação.

Ao executar o exemplo, você verá a seguinte saída:

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.

Para configurar, compilar e executar o exemplo

  1. Instale o ASP.NET 4.0 usando o seguinte comando.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.

  3. Para criar a solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

  4. Para executar o exemplo em uma configuração de máquina única ou cruzada, siga as instruções em Executando os exemplos do Windows Communication Foundation.