Asp.net

Todo sobre asp.net Web Forms

Comprimiendo VIEWSTATE en páginas ASP.NET

Si se le preguntase a los desarrolladores .NET sobre la característica más molestosa del framework orientado al Web. Muchos responderían que sería el VIEWSTATE.

VIEWSTATE literalmente tiene como funcion: "mantener el estado de vista" de una página ASP.NET, por ejemplo, una página que incluye un textbox y un botón. El textbox es renderizado con el valor foo precargado. Si el usuario ha cambiado ese texto en el formulario y luego hace submit de la forma, un desarrollador ASP.NET podría observar un evento TextChanged disparado desde el control con el cambio. Cómo puede ASP.NET conocer si el textbox ha cambiado o no? pues manteniendo el estado guardando esta información en el VIEWSTATE, dentro de un hiddenField enviado en la página al cliente llamado __VIEWSTATE.

Este valor almacenado tiene la tendencia "por natulareza" de crecer en tamaño, he allí la causa del enojo de muchos desarrolladores. Pero ellos no se dan cuenta que el ViewState está tratando de ayudar haciendo "completa la ilusión" de un modelo de eventos con estado bajo un protocolo estático como lo es HTTP. Esto lleva a la conclusión: "Es bueno tratar de minimizar el uso del ViewState".

Dino Esposito sugiere que el ViewState no debería exceder más del 30% del tamaño total de la página. Y Existen otra serie de tips y trucos para reducir el tamaño del ViewState. De todas maneras, usar compresión para hacer aun más pequeño el ViewState es fácil y rápido.

Comprimiendo el ViewState

Para este caso haremos uso de las librerías de compresión disponibles en el .NET Framework 2.0 específicamente la clase: DeflateStream.

  1. Generamos una clase ViewStateZip la cual expone 2 métodos Compress() y Decompress() y retorna un array de bytes (byte[]).
using System.IO.Compression;
public class ViewStateZip 
 { 
public static byte[] Compress(byte[] bytes)  
{  
 if (bytes != null) 
  {  
  MemoryStream memory = new MemoryStream();  
  DeflateStream compStream = new DeflateStream(memory, CompressionMode.Compress);  
  compStream.Write(bytes,0,bytes.Length);  
  compStream.Close();  
  return memory.ToArray();  
  } 
  else throw new ArgumentNullException("bytes");  
  }  
  
 public static byte[] Decompress(byte[] bytes) 
 {  
  if (bytes != null)  
  {  
 DeflateStream compStream = new DeflateStream(new MemoryStream(bytes),CompressionMode.Decompress);  
  MemoryStream memory = new MemoryStream();  24:  int theByte = compStream.ReadByte();  
 
  while (theByte != -1) 
 {  
  memory.WriteByte((byte)theByte);  
  theByte = compStream.ReadByte(); 
  }  
 compStream.Close();  
 return memory.ToArray();  
  }  
 else throw new ArgumentNullException("bytes");  
  }  
  
 }

Utilizamos aquí un nuevo objeto DeflateStream ubicando CompressionMode.Compress o CompressionMode.Decompress según sea necesario, y retornamos un arreglo de bytes, nada complicado, facil y sin problemas.

Ahora tenemos que hacer que la página comprima el viewState utilizando esta nueva clase: ViewStateZip. Para hacer esto sobreescribimos (override) dos métodos de la clase Page : LoadPageStateFromPersintenceMedium y SavePageStateToPersistenceMedium y ubicamos el ViewState comprimido dentro de un nuevo campo oculto (hiddenField) llamado __VSTATE.

 1: protected override object LoadPageStateFromPersistenceMedium() 
 2: { 
 3:  string vState = Request.Form["__VSTATE"]; 
 4:  byte[] bytes = Convert.FromBase64String(vState); 
 5:  bytes = ViewStateZip.Decompress(bytes); 
 6:  LosFormatter format = new LosFormatter(); 
 7:  return format.Deserialize(Convert.ToBase64String(bytes)); 
 8: } 
 9:  
 10: protected override void SavePageStateToPersistenceMedium(object state) 
 11: { 
 12:  LosFormatter format = new LosFormatter(); 
 13:  StringWriter writer = new StringWriter(); 
 14:  format.Serialize(writer, state); 
 15:  string viewStateStr = writer.ToString(); 
 16:  byte[] bytes = Convert.FromBase64String(viewStateStr); 
 17:  bytes = ViewStateZip.Compress(bytes); 
 18:  string vStateStr = Convert.ToBase64String(bytes); 
 19:  ClientScript.RegisterHiddenField("__VSTATE", vStateStr); 
 20: }

De esta manera hemos reducido considerablemente el viewState, sin muchas complicaciones y sin interferir con el funcionamiento de las páginas o los controles. Cada vez que la página quiera leer el ViewState, descomprimirá y leerá; cuando quiera guardar, comprimirá y guardará.

Existen situaciones en las que no puedes deshabilitar el ViewState en controles, como en un DataGrid, entonces en vez de ir disminuyendo uno por uno los items del ViewState.... Comprímelo! tendrás menos código enviado al cliente.

Existen algunas otras formas de manipular el ViewState, como guardarlo en sesión o almacenarlo en una base de datos, o cambiar la ubicación dentro de la página... Creo que esto será motivo de otro post futuro.

Happy Coding.

 

Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

No hay comentarios aún. Es excelente escuchar tu opinión, utiliza el formulario para comentar.

Deja tu Comentario

© Devlixir.com : blog de desarrollo web en espanol, asp.net mvc nhibernate — theme design by Javier Romero.
Javier Romero.