Olá! Saturday, 20 de April de 2024.



Dicas CódigoFonte.net
Monday, 09 de February de 2009

Armazenando a ViewState na Session no ASP.Net

Olá Pessoal,

Hoje vou explicar como diminuirmos um tamanho da página trocando a forma como é armazenado um mecanismo chamado ViewState no ASP.Net

Como vocês devem saber, as nossas páginas ASP.NET armazenam os estatos dos componentes no HTML gerado para o cliente, isto permite que os controles sejam preenchidos e seus valores possam ser acessados em nosso código .cs. É simplesmente uma maravilha, porém, caso tenhamos muitas informações nestes controles, nosso viewstate também crescerá e, como consequência, a página gerada para o usuário também.

Já cheguei a pegar projetos que consegui economizar mais de 70Kb só com informações de viewstate. Mas, como eu consegui isto? Armazenando o nosso viewstate no CACHE ou na Sessão!

No código a seguir, a classe, baseada nos parâmetros de configuração no web.config, irá armazenar nosso viewstate no CACHE ou na SESSION (recomendo colocá-los na SESSION).

Primeiro, você deve adicionar as seguintes configurações dentro do seu Web.config (lembre-se de colocá-las dentro da tag <appSettings>aqui</appSettings>.

Isto será necessário em nossa classe. Explico cada linha dentro do código.

Crie uma classe dentro do projeto Web, provavelmente o ASP.Net (se você não tiver) irá perguntar se deseja criar uma pasta chamada "App_Code". Diga sim. Esta nova classe será criada dentro desta pasta.

O código dela segue:

public abstract class ViewStatePage : System.Web.UI.Page {     protected override void SavePageStateToPersistenceMedium(object viewState) {         // cria uma chave única para este viewstate         string VSKey = "VIEWSTATE_" + Session.SessionID + "_" + Request.RawUrl + "_" + DateTime.Now.Ticks.ToString();         // verifica se o parâmetro do appsettings foi ativado         if (ConfigurationManager.AppSettings["ServerSideViewState"].ToUpper() == "TRUE") {             // verifica se o tipo de armazenamento é por CACHE ou Session             if (ConfigurationManager.AppSettings["ViewStateStore"].ToUpper() == "CACHE") {                 //armazena o viewstate no CACHE                 Cache.Add(VSKey, viewState, null, System.DateTime.Now.AddMinutes(Session.Timeout), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Default, null);             }                        else {                 // armazena o viewstate na sessão                 DataTable VsDataTable;                 DataRow DbRow;                 // verifica se já existe um datatable das viewstates na sessão                 if ((Session["__VSDataTable"] == null)) {                     // não existe, cria...                     DataColumn[] PkColumn = new DataColumn[1];                     DataColumn DbColumn;                     VsDataTable = new DataTable("VState");                                         //Coluna 1 - Nome: VSKey - PrimaryKey                     DbColumn = new DataColumn("VSKey", typeof(string));                     VsDataTable.Columns.Add(DbColumn);                     PkColumn[0] = DbColumn;                     VsDataTable.PrimaryKey = PkColumn;                     //Coluna 2 - Nome: ViewStateData                     DbColumn = new DataColumn("VSData", typeof(object));                     VsDataTable.Columns.Add(DbColumn);                     //Coluna 3 - Nome: DateTime                     DbColumn = new DataColumn("DateTime", typeof(System.DateTime));                     VsDataTable.Columns.Add(DbColumn);                 } else {                     // o datatable das viewstates já existe, pega ele da sessão                     VsDataTable = (DataTable)Session["__VSDataTable"];                 }                 // verifica se já temos uma viewstate com esta mesma chave                 // se sim, atualiza as informações na linha                 // do contrário, adiciona ela no datatable                 DbRow = VsDataTable.Rows.Find(VSKey);                 if ((DbRow != null)) {                     // linha encontrada! atualiza as informações sem criar uma nova linha                     DbRow["VsData"] = viewState;                 } else {                     // cria uma nova linha                     DbRow = VsDataTable.NewRow();                     DbRow["VSKey"] = VSKey;                     DbRow["VsData"] = viewState;                     DbRow["DateTime"] = System.DateTime.Now;                     VsDataTable.Rows.Add(DbRow);                 }                 // isto evita que o datatable tenha um grande tamanho.                 // apaga a primeira linha                 if (Convert.ToInt32(ConfigurationManager.AppSettings["ViewStateTableSize"]) < VsDataTable.Rows.Count) {                     VsDataTable.Rows[0].Delete();                                    }                 // grava o datatable na sessão                 Session["__VSDataTable"] = VsDataTable;             }             // registra um campo hidden da página             // que irá conter somente a key que foi gerada.             // com ela, será possível encontrar este viewstate armazenado             // no nosso datatable que está na session e, com isto, recuperar a sessão.             RegisterHiddenField("__VIEWSTATE_KEY", VSKey);         } else {             // chama o processo normal, pois não foi ativo no appsettings no web.config             base.SavePageStateToPersistenceMedium(viewState);         }     }     protected override object LoadPageStateFromPersistenceMedium() {         //Verifica se o ServerSideViewState está ativado         if (ConfigurationManager.AppSettings["ServerSideViewState"].ToUpper() == "TRUE") {             // pega a key que está no campo hidden criado             string VSKey = Request.Form["__VIEWSTATE_KEY"];                         // e valida             if (!VSKey.StartsWith("VIEWSTATE_")) {                 throw new Exception("Invalid VIEWSTATE Key: " + VSKey);             }             // verifica se utiliza CACHE             if (ConfigurationManager.AppSettings["ViewStateStore"].ToUpper() == "CACHE") {                 return Cache[VSKey];             } else {                 // ou session                 DataTable VsDataTable = (DataTable)Session["__VSDataTable"];                 if (VsDataTable != null) {                     DataRow DbRow = VsDataTable.Rows.Find(VSKey);                     if ((DbRow == null)) {                         //throw new Exception("Não foi possível encontrar o 'VIEWStateKey'. Tente limpar o cache de seu navegador ou recarregar esta página usando as teclas CTRL + F5.");                         return null;                     }                     return DbRow["VsData"];                 }                 return null;             }         } else {             // retorna o viewstate no modo normal             return base.LoadPageStateFromPersistenceMedium();         }     } }

Pronto. Criado a classe, você deverá alterar suas páginas para não mais herdar da classe

System.Web.UI.Page, mas sim da sua nova classe ViewStatePage.

Feito isto, todo o resto do processo será automático e, caso tenha curiosidade, poderá ver que seu HTML terá um tamanho bastante reduzido, comparado a quando era antes.

Caso deseje não mais utilizar este mecanismo, basta setar a configuração como False no seu parâmetro ServerSideViewState do Web.config.

Tem também uma outra forma de fazer este processo de economia do ViewState, é compactando ele. Veja como compactar um viewstate no ASP.Net neste artigo.

Bom, por hoje é só pessoal.

Até a próxima.


Comentários do artigo [Novo comentário]

Renato Mattos - 03 de March de 2010 - 18:08
Parabéns pelo artigo. O código funcionou perfeitamente sem erros e melhorou o desempenho de minha aplicação. Obrigado por compartilhar o seu código.
claudio furukawa - 24 de May de 2010 - 12:39
O artigo funciona, mas usando AJAX apresenta erros no codigo :

"Erro em tempo de execução do Microsoft JScript: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled."

Será que tem como resolver isto?
Alguem tem uma solução?

Abraços..
Emmanuel Alves Nóbrega - 06 de September de 2010 - 00:52
Iae kra, pra poder resolver o problema, altera a linha onde tem RegisterHiddenField("__VIEWSTATE_KEY", VSKey); para ScriptManager.RegisterHiddenField(this, "__VIEWSTATE_KEY", VSKey);
Para adicionar um comentário você deve efetuar o login


Gostou do CódigoFonte.net? Quer indicar a um amigo?
Preencha os campos a seguir.
Seu Nome:
Seu E-mail:
E-mail de seu Amigo:


CodigoFonte.net » Meu Mural » Competiva - Criação de Sites » Todos os Direitos Reservados © 2002/2010