ASP.Net: Why aren’t the changes I make to Viewstate in a control event available to subsequent postbacks

asp.netasp.net-ajaxviewstate

I'm writing a custom control in ASP.Net 3.5 WebForms, using ASP.Net AJAX. I'm building a state toggle into the control (expanded and collapsed modes). I've been trying to keep the current state of the control in ViewState, changing it in a server-side event handler manually:

object oExpanded = ViewState[ "Expandedness" ];
if(oExpanded == null)
{
    oExpanded = ListState.Collapsed;
}
ListState lsCurrentState = (ListState) oExpanded;
if(lsCurrentState == ListState.Collapsed)
{
    //code snipped - move to expanded mode here
    ViewState[ "Expandedness" ] = ListState.Expanded;
}
else
{
    //code snipped - move to collapsed mode here
    ViewState[ "Expandedness" ] = ListState.Collapsed;
}

I don't think it should matter, but the actual rendering happens in an updatepanel and the code above is in an event handler that's triggered asynchronously. The problem I have is that on the next postback, ViewState["Expandedness"] returns null. I've tried to use Fritz Onion's Viewstate Decoder tool to look at the actual contents of viewstate between postbacks, but it tells me the serialized data is invalid.

Have I taken a wrong approach here? What's the right way to tackle this problem?

Best Answer

You're right that it's OK for it to be in an UpdatePanel - this shouldn't make any difference.

I suspect that the ViewState is disabled either for your control or for one of its parents: if it's disabled for any parent (all the way up to the page), it'll be disabled for your control.

To get round this, you can use the page's ViewState dictionary instead of the one on your control.

I.e. instead of saying:

this.ViewState[ "Expandedness" ] = ListState.Expanded;

say:

this.Page.ViewState[ "Expandedness" ] = ListState.Expanded;

If it's possible that there's more than one instance of your control on the page, you'll need to ensure the ViewState key is unique, perhaps like this:

this.Page.ViewState[ this.ClientID + "Expandedness" ] = ListState.Expanded;

As an alternative (that will work even if ViewState's disabled for the page), you could consider storing the Expandedness in the ControlState. It's a bit trickier, but google it and you'll find a code sample pretty quickly. It's recommended you store only an absolute minimum of information in the ControlState, but a single flag like this is fine (and actually what it's designed for, really).

Related Topic