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 HttpCookieRequestSessionChannel
arquivo . 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 HttpCookieSessionBindingElement
partir 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 HttpCookieSessionBindingConfigurationElement
de 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
Instale o ASP.NET 4.0 usando o seguinte comando.
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.
Para criar a solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.
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.