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 os serviços WCF (Windows Communication Foundation) e os clientes do ASMX ou entre os clientes do WCF e os serviços do ASMX.
Quando um cliente chama um método Web em um serviço Web do ASMX baseado em sessões, o mecanismo do ASP.NET faz o seguinte:
Gera uma ID exclusiva (ID da sessão).
Gera e associa o objeto da sessão à ID exclusiva.
Adiciona a ID exclusiva a um cabeçalho de resposta HTTP Set-Cookie e envia ao cliente.
Identifica o cliente nas chamadas subsequentes com base na ID da sessão enviada a ele.
O cliente inclui essa ID da sessão nas solicitações subsequentes para o servidor. O servidor usa a ID da sessão do cliente para carregar o objeto da sessão adequado para o contexto HTTP atual.
Padrão de Troca de Mensagens do Canal HttpCookieSession
Este exemplo permite sessões para cenários semelhantes a ASMX. Na parte inferior da nossa pilha de canais, temos o transporte HTTP que dá suporte a IRequestChannel e IReplyChannel. O trabalho do canal é fornecer sessões para os níveis mais altos da pilha de canais. O exemplo implementa dois canais (IRequestSessionChannel e IReplySessionChannel) que viabilizam as sessões.
Canal de Serviço
O exemplo fornece um canal de serviço na classe HttpCookieReplySessionChannelListener
. Essa classe implementa a interface IChannelListener e converte o canal IReplyChannel na parte inferior da pilha de canais em um IReplySessionChannel. Esse processo pode ser dividido nas seguintes partes:
Quando o ouvinte de canais é aberto, ele aceita um canal interno do 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 manter apenas 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 em aberto é concluído, configuramos um loop de mensagens para receber as 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 da sessão e faz a demultiplexação para o canal de sessão apropriado. O ouvinte de canais mantém um dicionário que mapeia os identificadores da sessão para as instâncias do canal de sessão.
Dictionary<string, IReplySessionChannel> channelMapping;
A classe HttpCookieReplySessionChannel
implementa IReplySessionChannel. Os níveis mais altos da pilha de canais chamam o método ReceiveRequest para ler as solicitações dessa sessão. Cada canal de sessão tem uma fila de mensagens privada, que é preenchida pelo canal de serviço.
InputQueue<RequestContext> requestQueue;
Quando alguém chama o método ReceiveRequest e não há mensagens na fila de mensagens, o canal aguarda um tempo especificado para se desligar. Isso limpa os canais de sessão criados para clientes que não são do WCF.
Usamos o channelMapping
para acompanhar o ReplySessionChannels
, e não fechamos nossos canais subjacentes innerChannel
até que todos os canais aceitos tenham sido fechados. Dessa forma, HttpCookieReplySessionChannel
pode existir após o tempo de vida de HttpCookieReplySessionChannelListener
. Também não precisamos nos preocupar se o ouvinte receberá o lixo coletado abaixo de nós, pois os canais aceitos mantêm uma referência ao ouvinte por meio do retorno de chamada OnClosed
.
Canal do cliente
O canal do cliente correspondente está na classe HttpCookieSessionChannelFactory
. Durante a criação do canal, a fábrica de canais encapsula o canal de solicitação interna com um HttpCookieRequestSessionChannel
. A classe HttpCookieRequestSessionChannel
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 normalmente o canal de sessão que está em uso.
Associação e Elemento de Associação
Depois de criar os canais de serviço e de cliente, a próxima etapa é integrá-los ao runtime do WCF. Os canais são expostos ao WCF por meio das associações e dos elementos de associação. Uma associação consiste em um ou muitos elementos de associação. O WCF oferece várias associações definidas pelo sistema, por exemplo, BasicHttpBinding ou WSHttpBinding. A classe HttpCookieSessionBindingElement
contém a implementação do elemento de associação. Ele substitui os métodos de criação do ouvinte de canais e da fábrica de canais, para fazer as instanciações necessárias do ouvinte de canais ou da fábrica de canais.
O exemplo usa declarações de política para a descrição do serviço. Isso permite que o exemplo publique os requisitos de canal para outros clientes que podem consumir o serviço. Por exemplo, esse elemento de associação publica declarações de política para permitir que os possíveis clientes saibam que ele permite sessões. Como o exemplo habilita a propriedade ExchangeTerminateMessage
na configuração do elemento de associação, ele adiciona as declarações necessárias para mostrar que o serviço permite uma ação adicional 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 declarações de política criadas no 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>
A classe HttpCookieSessionBinding
é uma associação fornecida pelo sistema, que usa o elemento de associação descrito anteriormente.
Adição do Canal ao Sistema de Configuração
O exemplo fornece duas classes que expõem o canal de exemplo por meio da configuração. A primeira é um BindingElementExtensionElement para o HttpCookieSessionBindingElement
. A maior parte da implementação é delegada para o HttpCookieSessionBindingConfigurationElement
, que é derivado do StandardBindingElement. O HttpCookieSessionBindingConfigurationElement
tem propriedades que correspondem às propriedades no HttpCookieSessionBindingElement
.
Seção de Extensão do Elemento de Associação
A seção HttpCookieSessionBindingElementSection
é uma BindingElementExtensionElement que expõe HttpCookieSessionBindingElement
ao sistema de configuração. Com algumas substituições, são definidos o nome da seção de configuração, o tipo do elemento de associação e como criar o elemento de associação. Podemos 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 do Cliente e do Serviço. Ele consiste em dois testes: um teste usa uma associação com allowCookies
definido como true
no cliente. O segundo teste permite o desligamento explícito (usando o encerramento da troca de mensagens) na associação.
Ao executar o exemplo, você verá a saída a seguir:
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
Instale o ASP.NET 4.0 usando o seguinte comando.
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
Verifique se você executou o Procedimento de instalação única para os exemplos do Windows Communication Foundation.
Para compilar a solução, siga as instruções contidas em Como compilar as amostras do Windows Communication Foundation.
Para executar a amostra em uma configuração de computador único ou entre computadores, siga as instruções contidas em Como executar as amostras do Windows Communication Foundation.