Move ViewState server-side - asp.net

Okay so I have an ASP.NET application and I'm trying to reduce the overhead for our pages (our users have PCs that average 10 years old).
One of the approaches is to move ViewState server-side. We've plenty of RAM.
I followed the most often cited pattern for doing this here: http://authors.aspalliance.com/robertb/articles.aspx?articleId=2
Because it was written 7 years ago, I had to update some obsolete functions, namely RegisterHiddenField to ScriptManager.RegisterHiddenField and ConfigurationSettings.AppSettings to ConfigurationManager.AppSettings.
This seems to work fairly well, however as soon as I do an AJAX postback, I get the error
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: The state information is invalid for this page and might be corrupted.
I also noticed that there are now two hidden "__VIEWSTATE" fields on each page with one of them being empty, and one of them having the numeric value from my class. I think this is related to the issue -- perhaps the AJAX update is trying to reading from the empty one instead of the one with the value?
Does anyone know why this error occurs?

The answer is not to use the provided example at all. It's old and outdate, and there is a much better solution provided by the framework itself now.
protected override PageStatePersister PageStatePersister
{
get { return new SessionPageStatePersister(this); }
}
I just added those 4 lines to my BasePage class and voila - instant ~30% page size reduction and it works fine with the AJAX updates.

This is happening because you have not done anything to tell the MS AJAX framework about your new, server-side ViewState mechanism; it is getting the new values, which are simply trimmed-down keys that point to where to find it in the Session object. The AJAX framework knows nothing about that.
Reducing ViewState is most easily done by disabling it on controls where it's not needed at all. If you are using ASP.NET 4.0, you can do even better - disable it by default on the whole page, then only enable it where you need it.

Read this: http://www.hanselman.com/blog/MovingViewStateToTheSessionObjectAndMoreWrongheadedness.aspx
And use Http compression.

Related

ASP.Net Web Parts, personalization, and javascript

Folks,
I have some personalized properties on an ASP.Net Web Part that I would like to set via Ajax (for example, the size to which the user has expanded the WebPart using the jQuery Resizable plugin.)
I've read this question and answer, but I don't think it will work. Personalized properties are instance properties. (If they were static, they couldn't be user-scoped, could they?) A WebMethod, which must be static, can't access them.
You might be thinking that I could just use a hidden field and send my values back that way, but that assumes that a postback is done at least once after the values are set. In this case I can't guarantee that: the page in question displays a lot of data but doesn't take any user input other than for configuration.
I seem to recall that some Ajax techniques involve remotely instantiating a page on the server and going through at least part of the page life cycle, but the last time I messed with that was 2006 and I never could get it to work very well. I have the impression that modern Ajax techniques, even for ASP.Net, work in other ways.
So, does anybody have an idea of how this could be managed?
Thanks very much,
Ann L.
Webmethods only have to be static when they are page-based. Create a webservice in your project and stick non-static webmethods in there. You can even enable session state.

Losing the viewstate

I'm storing a few of my properties in the viewstate, so I can use them easily on Ajax requests. My property code looks like this:
public Language Language
{
get { return (Language)ViewState["controls_window_Language"]; }
set { ViewState["controls_window_Language"] = value; }
}
However, my customers have reported some errors, and when I've tracked it down, it's because Language is null. It doesn't happen every time; it appears to be totally random, and I can't reproduce the error. I'm also storing other properties inside the viewstate, and I'm using that property just before Language, so I havn't lost all viewstate.
Most logical reason would be that Language is overwritten, but the only time I write to it is when the page is first loaded.
What can be the reason for losing my viewstate property?
I'm not sure if this is the issue, but using the back/forward navigation in the browser can often cause unexpected results, especially on pages using a lot of asynchronous calls.
Edit: to clarify my thinking...
I'm suggesting this might be why users are seeing the error but you can't reproduce the problem. This is one step in troubleshooting I often forget about...
You say that you write to the viewstate when the page is first loaded.
How do you know that it is the first time the page is loaded, is there a navigation route in your app that could by pass the setting.
As a quick fix, you could try checking if the value is null and then returning a default value.
Try to see if there is a connection between the Session_OnError Event in the global.asax and your ViewState problem
See Dynamically adding controls to ASP.NET - viewstate is not retained after 20 minutes
One possible reason for "losing" ViewState content is Output Cache. I'm facing the same problem and the cause is caching (when I disable it, the problem doesn't occur).

I am trapped in the UpdatePanel trap

I have a very big problem. I am making a CRM (Costumer Relationship Management) System in ASP.NET 3.5
I have based my entire project on DevExpress.com controls and the use of UpdatePanels.
Now one of my pages, which is a central page in the whole system, contains a very big amount of possibilities and therefore a big amount of UserControls.
Now my problem is that it's getting really really slow because of the fact that UpdatePanels are reposting the entire page and not only the update panel. We are talking sometime 3-4 seconds before a popup window appears :(
Is there any way I can refactor this entire system away from UpdatePanels without breaking my neck?
Are there anyway I can optimize my use of UpdatePanels?
The ViewState is also absolutely giant.
Any good ideas are welcome...
There's no way to get around posting the entire page using UpdatePanels. In lieu of redesigning the app here are a couple things I'd try:
Disable viewstate for any controls that don't need it
Set the UpdateMode="Conditional" for your user controls. This won't get around posting the entire page but it will cut down on rendering time a little. Only the content for the specific UpdatePanel will be updated in the browser.
Make sure your user controls have short IDs. The way ASP.NET webforms names controls in the html these IDs get repeated quite a bit if you have a lot of server controls. Same goes for naming master page placeholders. I once cut a large page to half the size by renaming user controls and placeholders.
Since you're a DevExpress user, you might consider taking a little time to learn their CallbackPanel which will allow you to do asynchronous processing without the overhead of the UpdatePanel.
Alternatively (someone please correct me if I'm wrong) but if all of the postbacks are asynchronous (i.e. in an UpdatePanel), wouldn't it be theoretically possible to disable ViewState for the entire page (in the Page directive) without negative consequences? You'd have to test it completely off course, but it's worth a shot.
You'll have to replace some of the postbacks contained in your update panels with real AJAX calls, i.e. send only the data that is required for the action to the server and get back only what's required to update the view, getting rid of the postback and the UpdatePanels.
(You'll notice my use of the terms 'action' and 'view' - yes, I am an MVC fan. The situation you are in is typical of the mess that is easily got into using WebForms and the ASP.NET AJAX controls.)
I must be missing something. Why is your updatepanel is reloading the entire page. The point of an updatepanel is to refresh only what is in that panel, isn't it? Thanks for the explanation. I guess we're talking about reposting the page and not redrawing the panel as I thought.
Try turning off ViewState, especially for grids.
What kind of control is most common on your page? Try replacing those with your own lightweight UserControl or Server Control that does not use ViewState or ControlState
For all Interested I want to add a solution on how to get rid of the Viewstate data on clientside. It does give the server an extra load but if you are in the same situation as me and have a lot of server power and need to take the load of the clientside this is nice.
Let all your pages Derive from BasePage.cs looking like this
public class BasePage : System.Web.UI.Page
{
protected override void SavePageStateToPersistenceMedium(object viewState)
{
string vsKey = String.Format("VIEWSTATE_{0}_{1}_{2}", base.Session.SessionID, Request.RawUrl, DateTime.Now);
Session.Add(vsKey, viewState);
ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", vsKey);
}
protected override object LoadPageStateFromPersistenceMedium()
{
string vsKey = Request.Form["__VIEWSTATE_KEY"];
return Session[vsKey];
}
}
Now you have a key to the viewstate data session instead of the viewstate in your code...
Works like a charm for me on a website with 1000-1200 daily visitors as well.

Viewstate fails in IE Only

I have a page which contains some search fields to query a database, and display results. The viewstate is required to retain the lists of items in dropdowns.
Everything works fine in Firefox (3) & Chrome, but fails in Internet Explorer, but only sometimes (certain actions, such as resetting the form, which really just does a response.redirect with some querystring parameters)... what happens in the Viewstate gets dumped on the URL, and an error page is thrown.
Has anybody come across this before? Perhaps some pointers as to what might be causing this to occur in IE?
Thanks heaps,
greg
UPDATE:
On further investigation, i have determined that the actual error is this:
"Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster. "
Some more information that might help: This is caused by a user control that is being hosted in a content management system (Umbraco), which might have something to do with why the viewstate is being passed to the page (as the control is contained within a greater page in the CMS). I will investigate this a little further, but any other suggestions would be much appreciated.
cheers
greg
UPDATE 2:
Can anybody suggest why this only happens in IE (and not in FF or Chrome)?? Seems hardly likely its an issue with controls changing or machine keys or other suggestions I've read around the place, if other browsers can deal with it fine.
Any ideas what IE does differently that could cause this failure??
SOLUTION:
Turns out it was a really silly problem - I was using the wrong master template in the CMS, and therefore had 2 form tags. Remove extra form tag, problem solved!
Thanks heaps to bendewey for helping me solve this problem (see the comments in bendewey's post).
That's 4 hours of my life i'd love to get back... but glad i can move on now. Thanks again Stack Overflow community :)
It seems a bit wierd that your viewstate is posting to the the Url. The would happen if you had some custom form tag that was using a GET method instead of the default asp.net page level form tag.
If you need a form tag with the GET method I would set EnableViewState="false" on the Page declaration and setup some sort of list caching. Here is a sample, but you can find much better samples online (specifically ones that do double check locking). This way you can call this every postback and not worry about storing anything in the viewstate.
List<string> getCachedFields()
{
var searchFields = Cache["searchFields"] as List<string>;
if (searchFields == null)
{
searchFields = GetFieldsFromDbOrSomewhereExpensive();
Cache["searchFields"] = searchFields;
}
return searchFields;
}
We've fixed this problem using this blog's suggestion. Please have a look at it ...
I had to remove EnableViewStateMac="false" from the <pages> element to avoid the error in IE.

ASP.NET Custom Controls - Alternatives to PostBack?

On my journey into the depths of custom ASP.NET control development I am obviously getting my head around the ASP.NET PostBack model and how it affects control development.
I understand that controls have no "lifetime" in ASP.NET, and therefore must be re-initialized on each and every page load. We overcome this by persisting the objects values/parameters to the ViewState.
Many articles I read therefore suggest not using PostBack since this can add considerable overhead to the Page. I am not looking for how to disable it, I know that.
What I am looking for is:
What alternatives to we have to using the PostBack model to initialize controls?
I know we could use the QueryString, but that seems awfully messy, and obviously unreliable.
Ideally you could give me an overview of the architecture/design of a different approach and the pro's/con's of it..
Many thanks ^_^
Well, Session State is a server-side solution, with its own pile of cruft to deal with if you want to avoid ViewState altogether. Really though, using ViewState in a custom control is all fine and good - just be picky about what you store - only store deltas from the declared control state, don't store anything you're going to get on postback anyway (e.g. from a DB call), etc.
You have to store the values somewhere, so you are limited to the query string and hidden form fields. If you relate that to HTTP, basically it's either GET or POST parameters.
I suppose you could use cookies, but that would be really messy.
Store your object state in the session context: this will shift the burden of keeping state from the client to the server, which may be acceptable for small-scale intranet apps. For sites on the capital-I Internet, this won't work;
AJAX-enable your control: in this case, only state changes need to be posted back. Picking the right framework is key here; see http://www.asp.net/ajax/ajaxcontroltoolkit/samples/ for the official MS approach; many others are possible.
If you're truly looking for alternatives to the PostBack model altogether, then I would suggest researching the ASP.NET MVC Framework. I would love to kick WebForms to the curb and do all my stuff in MVC, but alas, legacy code is a tarbaby and rewriting is almost never the answer, so I plug onwards...
I think you still mis-understand controls somewhat. Controls only have the problem you describe when you add them to the page dynamically. If you declare your controls upfront in the aspx code then they build along with the page.

Resources