.NET and me Coding dreams since 1998!

10Jun/075

Life without View State

I think most of us have seen a "couple" of pages where view state was oversized (>x10 Kb) and that is totally unacceptable.

Typical use case I've seen is a Country drop down list which would contain list of all countries (200+ countries) with enabled view state.

When we call DataBind() on that country drop down list, bind countries information are stored in DropDownList.Items collection and that Items collection is stored in a ViewState which leads to bloated view state.

The approach I'm currently using to solve this problem is next one:

  • I'm disabling view state of DropDownList
  • I'm retrieving the list of countries from the cache and bind them on every post back

But, there is a problem with the fact that SelectedIndex property value is not been preserved during the post backs.

When the post back occurs, SelectedIndex is indirectly calculated based on the SelectedItem property, which is again based on DropDownList.Items collection which in case of disabled control view state is empty after post back.

 There are two solutions to this problem :

1) After the bind occurs, you can do next thing (I'll use countryDropDownlList in exampled line)

countryDropDownlList.Items.FindByText(Page.Request["countryDropDownlList"]).Selected = true;

where Page.Request["dropDownListName"] would contain text of the selected item when post back would occur

2) Bind the drop down list in the Init event and let the ASP .NET to do the 1) for you.
ASP .NET would try to do the same action in PreLoad event and to do that he only need already populated Items collection to do the selected item mapping

Example

Service component

 Let's pretend there is a country service component which retreives a list of countries from database or some other source

    internal class CountryService

    {

       internal static IEnumerable GetCountryList()

       {

          yield return  "Czech Republic";

          yield return "Malaysia ";

          yield return "Serbia";

          yield return "USA";

       }

    }

The page layout

Let's define a simple web page with a drop down list (which would contain list of countries) and a button (which would generate post back)

image

Control Html looks something like this

<asp:DropDownList ID="countryDropDownlList" runat="server" EnableViewState="false" Width="320px" />

<asp:Button ID="Button1" runat="server" Text="GeneratePostBack" /></div>

Data binding

The page has a context based lazy loaded method which calls the CountryService and retrieves the list of countries

        private IEnumerable GetCountryList()

        {

            IEnumerable countries = Cache["CountryList"] as IEnumerable;

            if (countries == null)

            {

                countries = CountryService.GetCountryList();

                Cache.Insert("CountryList", countries);

            }

            return countries;

        }

That method is been called each time time Page load event would occur

        protected void Page_Load(object sender, EventArgs e)

        {

            countryDropDownlList.DataSource = GetCountryList();

            countryDropDownlList.DataBind();

Restoring of the selected index

But, due to the fact that selected item information is also been stored in view state (which is disabled in our case) we have to add another line in Page_Load event handler code which would restore selected index without the usage of view state

            string selectedCountry = Page.Request["countryDropDownlList"];

            if (selectedCountry != null)

                countryDropDownlList.Items.FindByText(selectedCountry).Selected = true;

 

Testing the solution

Pick a country from a drop down list other then the first one, click on button to generate post back event and verify that your choice is been preserved after the post back

Conclusion

Considering how easy it is to implement drop down without the view state help I would say it is totally unacceptable (for me at least) seeing drop downs with the view state enabled

You can download source code of this small application from: Life without view state code example

 

Technorati tags: , ,
Comments (5) Trackbacks (0)
  1. This is quite an insidious gotcha in asp.net. The selection is reset because the drop down is databound in onload. Try binding it in oninit:

    protected override void OnInit(EventArgs e)

    {

               countryDropDownlList.DataSource = GetCountryList();

               countryDropDownlList.DataBind();

               base.OnInit(e);

    }

  2. Cristian is correct.

  3. As cristian said, OnInit is the way to go.  Also, if you bind or change property values in OnInit some of the issues with Viewstate go away.  

    Here’s a great post on viewstate, that was on DotNetKicks.com as while back:

    weblogs.asp.net/…/Truly-Understanding-Viewstate.aspx

  4. Everytime you databind it, it loses the selected state which is why this is happening.

    As well as putting it in oninit, you can also only bind on !postback to solve it.

  5. I am really surprised that Christian is right because I read about this problem in some of Dino Esposito books, where he explained that Items and SelectedItem information is stored in view state, so if you disable view state server has no ways to restore the selected item upon the post back

    Anyhow, I tried the OnInit thing and it works well and I would use it in future as much simpler one

    dkoehn – thanks for the cool link :)


Leave a comment

No trackbacks yet.