ASP.NET

Controle e utilização correta de ViewState

 

image002.jpg 

Fábio Campinho (fcampinho@insix.com.br) é Microsoft Certified Application Developer (MCAD), com 9 anos de experiência em desenvolvimento Web e hoje é Diretor de TI da INSIX Soluções Inteligentes.

 

image004.jpg
Thiago Almeida (thiago.almeida@neoti.com.br) é pós-graduado em Sistemas de Informação com Ênfase
em Componentes Distribuídos e Web, tem 5 anos de experiência em desenvolvimento WEB e hoje é Diretor de Desenvolvimento da NEOTI Studio de Tecnologia. As empresas participam da APL de TI do estado da Bahia.

 

Este artigo discute

Este artigo usa as seguintes tecnologias:

·       ViewState;

·       Performance de aplicações;

·       ControlState;

Visual Studio 2005, Visual Basic .NET e ASP.NET 2.0

 

Pense num passado não muito distante, relacionado ao desenvolvimento para ASP, lembrou? No desenvolvimento para ASP tínhamos que manter o estado da página na “mão grande”, toda vez que a página dava postpack perdíamos o conteúdo dos campos.

O ASP.NET trouxe um conceito novo e maravilhoso, o ViewState, que tornou o desenvolvimento de aplicações Web muito mais fácil, entretanto, como toda tecnologia o ViewState também tem seus aspectos negativos e o principal deles é aumentar o tráfego de rede.

Diversas vezes temos sites rápidos em desenvolvimento e lentos em produção. Nesse artigo mostraremos como utilizar corretamente o ViewState para ganharmos em performance.

Banco de dados

Utilizaremos o banco Northwind para os exemplos deste artigo. Sse você não tiver o banco, que por padrão não vem instalado no SQL Server 2005, faça o download no site da Microsoft no link  www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46a0-8da2-eebc53a68034&displaylang=en.

Vamos iniciar criando um Web Site chamado “ExemploViewState” (Figura 1).

 

image006.jpg 

Figura 1. Criando um site

Adicione um GridView na tela e carregue-o com a tabela Products através do SqlDataSource (“sdsProdutos”). Execute a página e visualize o código-fonte da mesma, gerado em HTML (Figura 2).

 

image008.jpg 

Figura 2. Examinando o código-fonte da página

Observe que temos um campo (hidden) chamado __VIEWSTATE, que possui 11.608 caracteres. Nossa página, excluindo esse campo, possui 18.047 caracteres, ou seja, o campo está acrescentando mais 64% no tamanho total da página.

Nesse teste colocamos somente um GridView na página e obtivemos a proporção de 64%, infelizmente podemos chegar a ter uma proporção maior que 300%, os campeões em aumentar o campo do ViewState são os controles GridView e DropDownList.

Preenchendo os controles

Vamos adicionar a essa mesma página um DropDownList apontando para a tabela Customer através de outro SqlDataSource (“sdsCliente”). Veja como ficará a página na Figura 3.

 

image010.jpg 

Figura 3. DropDown vinculado ao SqlDataSource.

Examinando o código-fonte novamente, o ViewState agora possui 14.936 caracteres, 3.328 a mais para um DropDownList com 91 linhas. Para entendermos na prática, vamos deixar em branco a propriedade DataSourceId do DropDownList e adicionar o código da Listagem 1 no Page_Load:

 

Listagem 1. Código para carregar os dados no DropDownList

If Not Page.IsPostBack Then

  DropDownList1.DataSourceID = "sdsClientes"

  DropDownList1.DataTextField = "ContactName"

  DropDownList1.DataValueField = "CustomerID"

  DropDownList1.DataBind()

End If

 

Observe que iremos ler os registros do banco uma única vez, quando a página executar o Load pela primeira vez. Adicione um Button ao lado do DropDownList, execute a página e clique no botão.

Os itens do DropDownList continuam a aparecer na página toda vez que clicamos no botão. Altere a propriedade EnableViewState do DropDownList para False e clique novamente no botão. Observe na Figura 4 que os itens do DropDownList não foram carregados.

 

image012.jpg 

Figura 4. DropDownList vazio e com ViewState desabilitado

No código do Page_Load estamos carregando os registro no DropDownList na primeira vez que executamos a página. No primeiro exemplo o ViewState está habilitado e quando a página é enviada para o browser o DropDownList grava no ViewState todos os itens que foram lidos do banco.

Quando clicamos no botão a página realiza um postback e todos os itens gravados no ViewState são enviados para o servidor e adicionados no DropDownList novamente, lembreando que uma página Web é stateless e não mantém os valores na memória. Esse ir e vir de ViewState representa no exemplo 3KB a mais para o DropDownList e 11KB para o GridView.

No segundo exemplo o DropDownList fica vazio porque desabilitamos o ViewState, impossibilitando o controle de ser preenchido por qualquer um dos dois métodos.

Desabilitando o ViewState

Primeiro vamos alterar a propriedade DataSourceId do DropDownList para sdsCliente e vamos comentar o código da Listagem 1. Depois vamos desabilitar o ViewState dos controles que estão na página, clicando em cada um, incluindo os SqlDataSource e alterar a propriedade EnableViewState para False.

 Finalmente execute a página novamente, exiba o código-fonte e verifique o tamanho do campo ViewState. O tamanho diminuiu de 14.936 caracteres para 256. Neste exemplo os objetos estão associados a um DataSource que vai ao banco e lê o conteúdo toda vez que a página executa um postback, o que torna desnecessário manter o ViewState habilitado.

Com a velocidade atual da Internet o que é mais rápido? A carga dos itens do DropDownList em uma conexão de internet que no Brasil tem uma média de velocidade de 256Kb/s ou a leitura do banco de dados em uma rede com 100 Mb/s?

Primeira regra para utilização do ViewState: desabilite o ViewState para controles que serão preenchidos a cada postback, principalmente GridView e DropDownList.

Menu

Até agora vimos objetos que faziam incrementos grandes no ViewState. No terceiro teste inclua um controle Menu e adicione alguns itens, conforme a Figura 5.

 

image014.jpg 

Figura 6. Estrutura do Menu

Realizei três testes: no primeiro simplesmente executei a página somente com o Menu. Nesse teste o campo Hidden ficou conforme Linha 1 na Listagem 2.

 

Listagem 2. ViewState gerado pelo Menu

Linha 1:

/wEPDwUKLTQzMzgyNTU1MGRkLR3t/OvJyVhXN99mttdodiwZeDA=

Linha 2:

/wEPDwUKLTQzMzgyNTU1MA9kFgICAw9kFgICAQ88KwANAQwUKwADZBQrAAJkPCs

ABgECFCsAAhYCHghTZWxlY3RlZGdkZGQYAQUFTWVudTEPD2QFDUZpbGVcTmV3IEl

0ZW1kT3S9LDt8k9NKZAa8hhIoGmZxLmc=

Linha 3:

/wEPDwUKLTQzMzgyNTU1MGQYAQUFTWVudTEPD2QFCEZpbGVcTmV3ZJTWUSkxFJ3

75DZeKj0uYtACrfDO

 

Depois cliquei em um item do menu com ViewState do menu habilitado e obtive o retorno conforme Linha 2. Finalmente desabilitei o ViewState do controle e cliquei novamente no menu e obtive o retorno conforme a Linha 3.

Vamos agora adicionar um Label antes do DropDownList de Clientes e alterar a propriedade ID para “lblCliente” e a propriedade EnableViewState para False. Acima do GridView adicione um Label e altera a propriedade Text para “Produtos”, alterando também a propriedade EnableViewState para False.

Adicione no Page_Load o valor “Cliente:” para a propriedade Text do lblCliente, conforme o código a seguir:

 

If Not Page.IsPostBack Then

  lblCliente.Text = "Cliente:"

End If

 

Execute a página e veja na tela o texto no Label. Clique no botão e observe que o texto vai retornar ao estado original definido na propriedade, no nosso exemplo Label, (Figura 7). Em ambos os casos o Label de produtos manteve a propriedade Text inalterada.

 

image016.jpg 

Figura 7. Label de Cliente com propriedade Text no estado original

Desabilitando o ViewState

Você deve perguntar qual o impacto que um Label, Button, TextBox, CheckBox, Validadores e outros controles, influenciam no tamanho do ViewState? Cada controle altera o tamanho do ViewState de uma forma diferente, na maioria dos casos são valores pequenos comparados ao GridView ou DropDownList.

Porém o tamanho do ViewState não é o único fator a ser levado em conta, toda vez que ocorre um postback para a página, durante a execução do PreLoad as informações do postback e ViewState são lidas e gravadas nos controles gerando processamento desnecessário para objetos que não tiveram suas propriedades alteradas.

Segunda regra para utilização do ViewState: desabilite o ViewState para controles que não têm suas propriedades alteradas durante a execução da página.

ControlState

O .NET 2.0 inovou ainda mais o controle do ViewState, criando um recurso chamado ControlState. O ControlState é responsável por manter os dados necessários para execução do controle, quando o ViewState está desabilitado.

Para os User Controls a utilização do ControlState deve ser programada utilizando as funções RegisterRequiresControlState, SaveControlState e LoadControlState.

Selecione o GridView e habilite as opções AllowPaging e AllowSorting. Execute a página e tente executar a paginação e ordenação. Se tentássemos executar esse mesmo exemplo com o .NET 1.x, ele não funcionaria.

No .NET 2.0, graças ao ControlState esses recursos continuam funcionando. Controles como GridView, FormView, DropDownList e Button utilizam os recursos do ControlState. Na Figura 8 temos um exemplo de Grid que executou paginação com ViewState desabilitado.

 

image018.jpg 

Figura 8. GridView com ViewState desabilitado e com recursos de ordenação e paginação.

Terceira regra para utilização do ViewState: quando desabilitar o ViewState execute um teste na tela para verificar se os controles continuam se comportando como esperado. Se o comportamento não for o esperado, habilite o ViewState do controle ou busque uma alternativa no code behind da página.

Em alguns casos recuperamos o valor do DropDownList através do Request(Control.UniqueID).

Conclusão

Quando desenvolvemos aplicações para Web, temos que lembrar que elas devem ser tão rápidas quanto as aplicações desktop. Acreditamos que uma tela deva demorar no máximo 2 segundos para aparecer em uma conexão discada.

Quarta regra para utilização do ViewState: sempre exiba o código-fonte da página e olhe o tamanho do campo hidden. Faça um teste no servidor de produção, quando estamos desenvolvendo, fazemos os testes das aplicações localmente, e quando colocamos em produção, percebemos o quanto esse campo pode influenciar na performance.

Sempre configure o ViewState de sua aplicação, a performance pode melhorar sensivelmente.