Introdução
Na parte anterior, vimos como podemos utilizar o evento onunload do javascript para detectar quando o usuário acessa um outro site ou quando ele fecha o browser. Entretanto, o evento onunload possui uma limitação, já que ele não faz distinção entre páginas da mesma aplicação ou páginas de outros sites. Esse evento sempre é chamado em resposta à saída da página atual. Como uma aplicação web normalmente é composta de várias páginas, temos que fazer com que o evento onunload somente seja chamado quando o usuário sair da aplicação, e não de uma página dela. É sobre isso que este artigo tratará.
O problema
Inicialmente, vamos reproduzir o problema. Com o Web Site Saida aberto no Visual Studio 2005, vá ao Solution Explorer e clique com o botão direito sobre o projeto. Escolha a opção Add New Item. Selecione o template Web Form e nomeie-o Pagina2.aspx, conforme a imagem abaixo:
Vá para o modo de Design e, a partir da Toolbox, arraste um controle HyperLink para a página. Na janela de propriedades do controle, vá a propriedade NavigateUrl e clique no botão
Altere também a propriedade Text para “Link para a página
Controle |
NavigateUrl |
Text |
HyperLink |
~/Pagina2.aspx |
Link para a página 2 |
No Solution Explorer, clique com o botão direito do mouse sobre Pagina1.aspx e escolha a opção View in Browser. Você verá uma tela parecida com a seguinte:
Clique no link que nos leva à Pagina2.aspx. Ao fazermos isso, o evento onunload é disparado, fazendo que a função javascript finaliza(), criada na segunda parte do artigo, seja chamada, expirando a sessão. Para comprovarmos que isso aconteceu, vá ao Control Panel do Windows ® Administrative Tools ® Event Viewer. Selecione o log Application e veja o log que foi gerado por nossa aplicação.
A solução
Para resolver o problema exposto anteriormente, iremos utilizar frames. Os frames do HTML dividem uma página web em partes independentes. Assim, podemos ter uma página composta por N outras páginas. Em nosso exemplo, só utilizaremos um único frame e a navegação entre as páginas ocorrerá dentro dele. O tratamento do evento onunload ficará na página que contém o frame. Assim, a troca de páginas de nossa aplicação, que ocorrerá dentro do frame, não provocará a chamada do evento onunload, que só será disparado quando acessarmos um outro site ou fecharmos o browser.
No Solution Explorer, clique com o botão direito do mouse sobre o Web Site Saida e escolha a opção Add New Item. Escolha o template HTML Page e no campo Name, escreva index.htm. Vá para o modo Source da página, para termos acesso ao código HTML. Substitua o conteúdo pelo código abaixo:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script language="javascript" type="text/javascript">
function finaliza()
{
var xmlHttp=false;
try {
xmlHttp = new XMLHttpRequest();
} catch (e1) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e2) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
xmlHttp.open("GET", "Finaliza.aspx", true);
xmlHttp.send(null);
}
</script>
</head>
<frameset rows="100%" cols="100%" onunload="finaliza();">
<frame src="Pagina1.aspx" frameborder="0" />
</frameset>
</html>
Perceba que, além de definirmos um frame que ocupará a janela inteira do browser, também foi colocado o código da função javascript finaliza() bem como sua chamada no evento onunload da tag <frameset>. Assim precisamos ir à Pagina1.aspx e retirar a declaração da função javascript finaliza() e a chamada do evento onunload.
No Solution Explorer, clique com o botão direito do mouse sobre a página index.htm e escolha a opção View in Browser. Você verá a página carregada, com o conteúdo da Pagina1.aspx dentro do frame. Clique no link para ir à Pagina2.aspx e verifique no Event Viewer do Windows que o log de sessão expirada não foi gerado. Clique no link para voltar à Pagina1.aspx e confirme novamente que o log não foi gerado. Perceba também que enquanto navegamos entre as páginas, a URL na barra de endereços do browser não se altera. Isso acontece porque a navegação ocorre dentro do frame, enquanto que a URL aponta para a página que contém o frame. Agora, experimente acessar outro site ou fechar o browser. Volte ao Event Viewer e confirme que o log foi gerado, comprovando que o evento onunload foi disparado.
Conclusão
Com esta alteração, a aplicação web agora é capaz de gerar notificações de saída do usuário no momento certo, já que agora o evento onunload não é disparado a cada mudança de página. Nesta série de artigos, vimos como utilizar recursos do lado servidor e do lado cliente para detectar quando o usuário deixa uma aplicação ASP.NET. Combinando os dois, estudamos as limitações e as soluções para contornar as mesmas, permitindo que algum processamento seja feito neste momento.
Referências
Código fonte do exemplo deste artigo
http://www.aspneti.com/artigos/ExemploDetectarSaida.zip
Gerenciamento de Estado no Servidor – Parte 1 http://www.msdnbrasil.com.br/sharepedia/visualizarartigo.aspx?id=57763
Gerenciamento de Estado no Servidor – Parte 2
http://www.msdnbrasil.com.br/sharepedia/visualizarartigo.aspx?id=57906
Dynamic HTML and XML: The XMLHttpRequest Object
http://developer.apple.com/internet/webcontent/xmlhttpreq.html
Frames in HTML documents
http://www.w3.org/TR/html401/present/frames.html
Sobre o Autor
Ricardo Oneda Pereira de Toledo é formado em Processamento de Dados pela Faculdade de Tecnologia de São Paulo, é MCAD – Microsoft Certified Application Developer, com ênfase