Losing the viewstate - asp.net

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).

Related

Failed to load viewstate error after moving website to a new server

I don't really know where to start with this one. I am getting:
`Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.`
after moving a website to a new server. The exact same code works on my other server. It happens when I submit one of my forms (but doesn't do it on all form submissions).
Any ideas what can cause this so I have somewhere to look?
Using: ASP.NET 2.
EDIT: I am adding some user controls to a placeholder dynamically at runtime but this same code is working ok on my other server. I have tried clearing the controls in the place holder before adding new ones (as I saw a post about that) but it hasn't helped.
EDIT2: It seems that the postback is just failing. It isn't going into the onClick code of the button either so something is deffintiely screwy .. If I try / catch the exception it seems that all the controls are still added successfully ... Setting my Dynamic UC's to EnableViewState = false resolves this particular error.
EDIT3: Ok, I think I may have a handle on what is happening. For some reason on the old server the form action is default.aspx?action=amend but the new server is showing amend.html?action=amend so I think the re-write module is messing up in IIS. This would explain the control adding issue as well because the action is happening 2 times (I think). I will look into the Rewrite module and see if anything is wrong then post back.
Please, have a look at these articles:
http://blog.typps.com/2008/01/failed-to-load-viewstate-typical.html
http://weblogs.asp.net/guys/archive/2004/12/05/275321.aspx
Or try a simple temporary solution - disable viewstate for this placeholder. Either way, I'm puzzled why it actually works on your first server. I'd be glad if someone else will be able to clarify this subject more.
It turns out that the post back Url for the form is wrong on this server (unsure why at the moment, I will update when I know). This is causing the dynamic controls to be added in an unexpected way and causing the error. I noticed this when I managed to post my form and the content didn't update. I manually adjusted the action url using firebug and all is well.
Worth looking at walther's answer regarding dynamic controls and the viewstate though.
Not sure what caused it but I am manually setting the form action in the page load now and it seems to have solved the issue.

Move ViewState server-side

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.

ASYNC postbacks happening when SupportsPartialRendering is set to false

We're getting a confusing error on two of our pages in our ASP.NET application. Both pages originaly had tags to reload the page every so often if a user sat on it for a while, but opted to remove those in favor of some AJAX flavoring. Specifically, we created timer controls on the page and wired the timer's tick event as a trigger for an update panel to reload a portion of the page. The page(s) also have scriptmanagers on them as we don't have one on the master page. This largely works great except we're getting a lot of these errors:
"The page is performing an async postback but the ScriptManager.SupportsPartialRendering property is set to false."
It is my understanding that if the .NET framework detects a browser doesn't support partial rendering it will set the ScriptManager.SupportsPartialRendering value to false and we're NOT overriding this in any fashion. Therefore, the pages shouldn't be by performing async postbacks if that value is false, but based on the error the postbacks are still happening and the page is throwing an exception.
Curiously, the user agent always seems to be GoogleBot or "Mozilla/4.0 (Windows 98; US) Opera 10.00 [en]".
I'd apperciate some insight. We've toyed with the idea of forcing the SupportsPartialRendering to true, but that doesn't explain why ASYNC postbacks are even occuring if the .NET framework is setting this to false based on the the browser caps.
I'm finding this, too. It appears that newer browsers will also cause this exception. The items that I've found so far -- though I've not resolved my own scenario -- are as follows:
Ensure the <xhtmlConformance mode="Legacy" /> is not set to Legacy
Potentially by removing Hidden fields
You can disable partial rendering entirely by setting ScriptManager.EnablePartialRendering to false. This will force an update panel to reload the entire contents of the panel at once.
I find SupportsPartialRendering confusing as well because of the name and because it is doing two things.
It acts as a flag to determine if the browser supports partial-page rendering. As a flag, it won't actually prevent asynchronous postbacks, that's why you get the error still.
You can use it as an override. You can allow asynchronous postbacks regardless of what the browser is, but you can't prevent it with this property.
Cheers.

Can a URL change on postback?

I only need to parse URL Request.Querystrings on GET, not on postback, right?
if(!IsPostBack)
{
Viewstate["magic_number"] = Parse(Request.Query);
}
The user can't be expected to modify the URL in the Request for subsequent postbacks, or can they?
Motivation for question-- I don't control the javascript snippet that does the postback, so it's something of blackbox to me.
The URL is not expected to change. But remember that each postback is a new instance of your page class. So if you didn't save the results somewhere on the first view you need to be prepared to do it again on the next one, and so on. In this case you saved it to ViewState, and so that should be fine.
However, I suspect you wouldn't be asking the question unless you had observed behavior that led you to suspect otherwise. So let's consider for a moment what things could cause this to break:
It is possible to modify ViewState at the client where you saved your results (though not trivial and definitely not recommended).
You can fake a postback before the initial page view.
You can use javascript to alter the posted url.
However, for all these things you would certainly know if you have written anything to do that.
Your assumption is correct, the URL is not expected to be modified in subequent post backs and you need to parse the query string only on the GET, which happens the first time the page is loaded.
The URL does not normally change for a postback.
It's of course possible to use a tool like FireBug to edit the URL in the form tag before the postback, but then you probably don't want the value that the user injected anyway, but the original value.
As others have pointed out, The URL is not expected to change. Of course if we lived in a perfect world you would never get email spam and noone would ever attempt to do anything malicious to your website.
In the real world you should expect that malicious people will attempt to hijack your website and need to be concerned with things like injection attacks
You should never make any assumptions that the data received on a postback is valid.

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.

Resources