Add your own alternative version
Stats
309.1K views 163 bookmarked
Posted
10 Jul 2006
|
Comments and Discussions
|
|
Hi,
In my scenario, i have a sharepoint list consisting of 16900 items that is shown up in a grid on the asp .net page. After adding your code i face an issue where in if i click on an item on the second page of the grid, the first page item opens up.
Am i missing something ?
Can you please help me out with a solution to this ?
Thanks! 
|
|
|
|
|
the code is fine and clean. easy to understand. and it works fine if i should be adding this
protected override object LoadPageStateFromPersistenceMedium(){...}
and
protected override void SavePageStateToPersistenceMedium(object viewState){...}
methods to each page in my application.
However my application is using so many pages.
now my Question.
is there no way to implement these method on a masterpage where all the pages are nested?
Please reply
olaleke
|
|
|
|
|
Don't do this at masterpages.
It should have nothing to do with masterpage.
The proper way to do it is by creating a class inherit System.Web.UI.Page like this:
public class BasePage : System.Web.UI.Page
{
protected override void SavePageStateToPersistenceMedium(object viewState)
{
}
protected override object LoadPageStateFromPersistenceMedium()
{
}
}
Then inherit all your pages with this class:
public class WebForm1 : BasePage
{
}
|
|
|
|
|
I have a problem, when load a data in the ViewState using function LoadPageStateFromPersistenceMedium, i show the error next "The serialized data is invalid."
My error is directly in the line return formatter.Deserialize(Convert.ToBase64String(bytes));
modified 20-Jun-13 13:45pm.
|
|
|
|
|
Sorry, it's my problem by a bad code.
|
|
|
|
|
|
IIS support the compression and all browsers support it as well.
When you see your ViewState was originally 38Kb you got to remember that you see it AFTER decompression by the browser.
So the actual amount of data that was sent from IIS to the browser would be 17Kb (what you saw after your code ran).
Bottom line your code will only decrease performance since you doing compression twice on those 38Kb. First your code then IIS will do it.
But you are not saving any bandwidth.
Just my 2 cents.
George.
|
|
|
|
|
HTTP compression only works from the server to the client.
When you do a postback, you send data to the server (including the viewstate) uncompressed, so you are saving bandwidth.
|
|
|
|
|
I am getting same problem,
After using following code for compression,
using System.IO;
using System.IO.Compression;
/// <summary>
/// Summary description for Compressor
///
public static class Compressor
{
public static byte[] Compress(byte[] data)
{
MemoryStream output = new MemoryStream();
GZipStream gzip = new GZipStream(output, CompressionMode.Compress, true);
gzip.Write(data, 0, data.Length);
gzip.Close();
return output.ToArray();
}
public static byte[] Decompress(byte[] data)
{
MemoryStream input = new MemoryStream();
input.Write(data, 0, data.Length);
input.Position = 0;
GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true);
MemoryStream output = new MemoryStream();
byte[] buff = new byte[64];
int read = -1;
read = gzip.Read(buff, 0, buff.Length);
while (read > 0)
{
output.Write(buff, 0, read);
read = gzip.Read(buff, 0, buff.Length);
}
gzip.Close();
return output.ToArray();
}
}
protected override object LoadPageStateFromPersistenceMedium()
{
string viewState = Request.Form["__VSTATE"];
byte[] bytes = Convert.FromBase64String(viewState);
bytes = Compressor.Decompress(bytes);
LosFormatter formatter = new LosFormatter();
return formatter.Deserialize(Convert.ToBase64String(bytes));
}
protected override void SavePageStateToPersistenceMedium(object viewState)
{
LosFormatter formatter = new LosFormatter();
StringWriter writer = new StringWriter();
formatter.Serialize(writer, viewState);
string viewStateString = writer.ToString();
byte[] bytes = Convert.FromBase64String(viewStateString);
bytes = Compressor.Compress(bytes);
ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
}
When I click on next button my application gets stopped.
Please help me what should i do?
Regards,
Amit
|
|
|
|
|
Great article! Significant performance improvement! Simple, praticle and direct to the point! Congratz!
|
|
|
|
|
Why do you name the field "__VSTATE"?
Are there cases in which savings in viewstate size may become performance bottleneck?
Thanks.
|
|
|
|
|
It saves me a lot of time!
Thank you very!!!
Luisa
|
|
|
|
|
|
This is the result of the viewstate in my application:
Using your example:
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Iv7vX/M3/e1+zV/3F/z+v/9JtWzrqmxe5b9oXdT5y6ppn2TTt79Xfv37//6/za/56/7YyTyfvn1Svdv9TX/dH/v03sHuzt6Dg3uz/wcl/rgoPwAAAA=="
Without using your example, same webform:
="/wEPDwUJNjM4MTAyNzgzZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAQUJQ2hlY2tCb3gxeC4oWoGK+hZjCjTZmpgxFgH6MxQ=
¿Am I doing something wrong?
|
|
|
|
|
I have the same result: my viewstate is bigger with compression than without.
|
|
|
|
|
I came across this article. It's a great article. Thanks for sharing.
I tried to play around with sample a bit. I found out that ViewState is really compressed if data is long enough. There are many times the size of ViewState data is grown after compression. For short data, the compression is not effeciently.
Here's my suggestions for optimizing codesnippets. First we insert a header (1-byte size) before the first byte of ViewState. This header tells whether ViewState data is compressed or not.
protected override void SavePageStateToPersistenceMedium(object viewState)
{
...
bytes = Compressor.Compress(bytes);
//NEW CODESNIPPET:
byte[] tmp = Compressor.Compress(bytes);
//If size is really smaller than the original one after compression, the compressed array is preferable
if (tmp.Length < bytes.Length)
{
byte[] tmp2 = new byte[tmp.Length + 1];
System.Buffer.BlockCopy(tmp, 0, tmp2, 1, tmp.Length);
tmp2[0] = 1; //Compressed. Save into the first byte
bytes = tmp2;
}
else
{
byte[] tmp2 = bytes;
byte[] tmp3 = new byte[bytes.Length + 1];
System.Buffer.BlockCopy(tmp2, 0, tmp3, 1, tmp2.Length);
tmp3[0] = 0; //Not Compressed. Save into the first byte
bytes = tmp3;
}
ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
}
protected override object LoadPageStateFromPersistenceMedium()
{
byte header = bytes[0]; //Extract data of the first byte. This data tells whether ViewState has been compressed or not previously
byte[] tmp = new byte[bytes.Length - 1];
System.Buffer.BlockCopy(bytes, 1, tmp, 0, bytes.Length - 1);
bytes = tmp;
if (header == 1)
bytes = Compressor.Decompress(bytes);
LosFormatter formatter = new LosFormatter();
return formatter.Deserialize(Convert.ToBase64String(bytes));
}
Is this codesnippet good?
|
|
|
|
|
First of all the default compression of gzip isn't very good. Using a more efficient compression method could eliminate this problem and have a higher compression ratio.
Second, your optimization would optimize for size but not for speed. My idea would be that instead of doing the actual compressing and then compare the size with the size of the uncompressed viewstate, the code would be faster to define a threshold that will generally mean that below that size threshold, compression isn't effective and should be skipped. so, if the size of the view state is for example smaller than 512 bytes then skip compression, otherwise compress it.
This way it would generally optimize for size without losing speed
PURPOSE: Delays program execution until designated condition is indicated.
|
|
|
|
|
Hi!!
(please excuse my english).
Thanks for the code, works 99% ok!
Also changed the ScriptManager.RegisterHiddenField like some poster adviced.
But i have some problems with usercontrols (.ascx) inside UpdatePanel.
My usercontrols have dropdown combos and i notice the the contains of the combos dissaperar.
Any advice?
Thanks in advance.
Best regards,
Homero Gonzalez.
|
|
|
|
|
Actually the Viewstate it's a great tool for Developing web App. but it can turn out to be a Performance trouble if it grows too much, your article it's a smooth workaround. Thanks for sharing it.
it also reduces the chance of getting the horrible MAC problem.
Great!
|
|
|
|
|
The magic number in GZip header is not correct. Make sure you are passing in a GZip stream
I got this error while in this line
read = gzip.Read(buff, 0, buff.Length);
pls help me out soon.
Maharajan,
software engineer,
Kom7 technologies,
India..
|
|
|
|
|
This is a great solution. I use the viewstate a lot, and even though I disable it where I can, I still get a viewstate larger than I would like.
Consider this modification:
public static class Compressor<br />
{<br />
<br />
public static byte[] Compress(byte[] data)<br />
{<br />
using (MemoryStream output = new MemoryStream())<br />
{<br />
using (GZipStream gzip = new GZipStream(output, CompressionMode.Compress, true))<br />
{<br />
gzip.Write(data, 0, data.Length);<br />
gzip.Close();<br />
return output.ToArray();<br />
} <br />
}<br />
}<br />
<br />
public static byte[] Decompress(byte[] data)<br />
{<br />
using (MemoryStream input = new MemoryStream())<br />
{<br />
input.Write(data, 0, data.Length);<br />
input.Position = 0;<br />
using(GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true))<br />
{<br />
using (MemoryStream output = new MemoryStream())<br />
{<br />
byte[] buff = new byte[64];<br />
int read = -1;<br />
read = gzip.Read(buff, 0, buff.Length);<br />
while (read > 0)<br />
{<br />
output.Write(buff, 0, read);<br />
read = gzip.Read(buff, 0, buff.Length);<br />
}<br />
gzip.Close();<br />
return output.ToArray();<br />
} <br />
}<br />
} <br />
}<br />
}
it's exactly the same as before, but since all the objects used are IDisposable, I've initiated them with "using()".
Here's why:
http://www.angrycoder.com/article.aspx?ArticleID=336[^]
I think there is a danger with the original code for memory leaks, because the objects are not disposed of.
What do you think?
|
|
|
|
|
Given that the streams I used here are always managed in RAM, I supposed that the use of using could be avoided because the objects are disposed at the end of their scope (I hope). At any rate, it's surely a good practice to use using .
|
|
|
|
|
Good Article! Great idea!.
I 've attempted to use this in an ASPNet 2.0 web application with AJAX 1.0 and found I get an ObjectDisposedException after selecting a grid row. I've used the correct ScriptManager reference for registering the hidden field. For some reason the stream is closed prematurely. The stack trace is
at System.IO.__Error.StreamIsClosed()<br />
at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)<br />
at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)<br />
at System.IO.Compression.GZipStream.Read(Byte[] array, Int32 offset, Int32 count)
the error occurs in the DecompressViewState in the ViewStateCompressor.cs is
static byte[] DecompressViewState( byte[] compData)<br />
{<br />
.....<br />
byteRead = gzip.Read(buf, 0, buf.Length);<br />
.....<br />
}
I'm trying to fathom the reason for the exception.
|
|
|
|
|
 That's because you haven't taken into account "AsyncPostBacks". During every PostBack you need to Compress / Decompress the ViewState. This needs special handling during an AsyncPostBack where MS Ajax is involved. If you're using a differt Ajax Framework, sorry, I can't help you, but it's the same concept. You don't need to modify you Compress / Decompress routines, just the Restore/Save PageStateToPersistanceMedium.
Notice the bolded text in the "SavePageStateToPersistenceMedium" method. During an AsyncPostBack you need to re-register the HiddenField, however, you cannot simply just do this the same way. If you're in an AsyncPostBack, you need to use the ScriptManager methods to do this. If you're just in the first PageLoad or subsequent PostBacks, then using the ClientScript is fine.
protected override object LoadPageStateFromPersistenceMedium()
{
try {
string compression = ConfigurationManager.AppSettings["viewStateCompression"];
if (string.IsNullOrEmpty(compression)) compression = "true";
if (bool.Parse(compression)) {
string viewState = Request.Form["__VSTATE"];
if (viewState.EndsWith(",")) viewState = viewState.Substring(0, viewState.Length - 1);
byte[] bytes = Convert.FromBase64String(viewState);
bytes = BasePage.Decompress(bytes);
viewState = Convert.ToBase64String(bytes);
if (string.IsNullOrEmpty(viewState)) return null;
LosFormatter formatter = new LosFormatter();
return formatter.Deserialize(viewState);
}
else
return base.LoadPageStateFromPersistenceMedium();
}
catch (Exception) { throw; }
}
protected override void SavePageStateToPersistenceMedium(object state)
{
StringWriter writer = new StringWriter();
try {
string compression = ConfigurationManager.AppSettings["viewStateCompression"];
if (string.IsNullOrEmpty(compression)) compression = "true";
if (bool.Parse(compression)) {
LosFormatter formatter = new LosFormatter();
formatter.Serialize(writer, state);
string vState = writer.ToString();
byte[] bytes = Convert.FromBase64String(vState);
bytes = BasePage.Compress(bytes);
vState = Convert.ToBase64String(bytes);
System.Web.UI.ScriptManager sm = System.Web.UI.ScriptManager.GetCurrent(this);
if (sm != null && sm.IsInAsyncPostBack)
System.Web.UI.ScriptManager.RegisterHiddenField(this, "__VSTATE", vState);
else
Page.ClientScript.RegisterHiddenField("__VSTATE", vState);
}
else
base.SavePageStateToPersistenceMedium(state);
}
catch (Exception) { throw; }
finally {
if (writer != null) { writer.Dispose(); writer = null; }
}
}
|
|
|
|
|
You saved my Butt today, you code works perfectly, i didnt consider the ajax part..
Im using radcontrol to initiate ajax in my application.
From
M.Paige
|
|
|
|
|
|
General News Suggestion Question Bug Answer Joke Praise Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
|