Quando expliquei sobre o tempo de vida de uma página ASP.Net, disse que existem mecanismos que uma aplicação pode utilizar para guardar estado entre requisições. Um desses mecanismos é o ViewState.
ViewState é uma string armazenada em um campo oculto, dentro do HTML gerado para a sua página. Se você criar uma nova aplicação ASP.Net, sem nada, rodar, e olhar o código fonte da página vazia que foi gerada, vai encontrar algo parecido com isso:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body>
<form name="_ctl0" method="post" action="WebForm1.aspx" id="_ctl0">
<input type="hidden" name="__VIEWSTATE" value="dDwtNjU0MzcyMTk1Ozs++0nkj9wYEIHhJubPoNiG5UGjjaI=" />
</form>
</body>
</html>
É fácil de ver o viewstate nesse código fonte. Ele é um conjunto de dados sobre a página e seus componentes, concatenado com um hash gerado no servidor para evitar ataques onde alguma pessoa maliciosa altere o conteúdo dessa string e faça um postback para o seu servidor. Essa string está em Base64, e é simples decodificar, como por exemplo usando o ViewState Decoder. Vamos ver o que o viewstate da nossa página vazia possui:
<?xml version="1.0" encoding="utf-16"?>
<viewstate>
<Triplet>
<String>-654372195</String>
</Triplet>
</viewstate>
Não existe nada de interessante ainda, apenas o hash da página, que evita alterações não permitidas.
Cada componente colocado em uma página ASP.Net vai salvar seu estado no ViewState, para que cada vez que acontecer um postback esse componente possa voltar a ser exibido exatamente como estava antes, sem precisar fazer nova inicialização ou trazer os dados novamente do banco de dados, e assim por diante. Isso é prático, mas pode deixar o ViewState incrivelmente grande e aumentar bastante o tamanho da sua página - e o tempo de carregamento por consequência.
Vamos fazer um teste para ver como isso funciona: coloque um DropDownList, um botão e um ListBox em uma nova página ASP.Net. Coloque o seguinte código no PageLoad para popular o DropDownList com algumas opções:
procedure TWebForm1.Page_Load(sender: System.Object; e: System.EventArgs);
begin
if not IsPostBack then
begin
DropDownList1.Items.Add('Um');
DropDownList1.Items.Add('Dois');
DropDownList1.Items.Add('Três');
end;
end;
Escreva também o código apropriado no botão para adicionar no ListBox o item selecionado do DropDownList. Rode a aplicação, selecione alguns items diferentes e aperte botão para ir adicionando esses items. Repare como o DropDownList mantém os items mesmo não sendo preenchido toda vez, e como o ViewState vai aumentando o tamanho cada vez que você adiciona um item novo. Utilize a ferramenta que mostrei anteriormente para ver o que está dentro dele cada vez que você pressiona o botão.
Para ver o que o ViewState faz de verdade, vá até o DropDownList e altere a opção EnableViewState para False. Rode a aplicação de novo e perceba como após a primeira atualização de página, os items que tinham sidos adicionados no DropDownList não estão mais lá. Podemos alterar nosso código que carrega os items no PageLoad para fazer o carregamento toda vez, e não só quando não for Postback. Tirando o if, os items são carregados a cada requisição, diminuindo o tamanho do viewstate. Em uma aplicação mais realista, é bem possível que esses dados estivessem vindo do banco de dados, então estariamos fazendo bem mais consultas, o que geralmente é prejudicial à performance e à carga do servidor. Nesse caso deve se usar o bom senso e considerar o que é mais importante para cada situação: não há uma regra padrão.
Outro experimento interessante para entender o funcionamento do ViewState é desligar o ViewState da ListBox, e rodar o exemplo novamente. Acho que neste ponto você já consegue imaginar como a aplicação vai se comportar, e entender o motivo. O último teste a fazer é trocar a DropDownList por um TextBox, e rodar a aplicação com o ViewState da TextBox ligado e desligado. Surpreso por ver o conteúdo da TextBox sendo mantido mesmo com o ViewState desligado? É porque o conteúdo de campos em formulários é submetido normalmente a cada requisição, sem precisar de espaço extra no ViewState para isso.
O ViewState não serve apenas para guardar o estado de controles que estão na página - você pode guardar os dados da sua aplicação nesse campo oculto, se eles forem aplicáveis só para uma página. Vou explicar como fazer isso no próximo artigo.