ASPNET AJAX Control Toolkit Tip

In this day and age, async is king. We are used to pages loading asynchronously and deferring the loading of not-as-important scripts or images until later in the page lifecycle. We do it with lazy loading, with AJAX, and with smaller calls to the service layer to populate parts of the view model.

However, such a convention does not necessarily jive with ASP.NET webforms. A webform has a full posted-back page lifecycle, consisting of a page initialization, to a page load, postback, and unload (there are more stages, but that’s the gist). Every action on the page generates a post-back, forcing the entire page lifecycle to start again. Depending on your configuration, this can degrade the user’s experience.

With webforms, the user’s state was used to carry their selection or preferences across requests. These sorts of things can also be stored in the ViewState and can allow for a page to be functional. Note, however, that ViewStates (client side) and SessionStates (server side) can get bloated and overloaded, so they should be used carefully.

By default, the ViewState on a page is set to True.

I was updating a page to be more dynamic and responsive to user input. At the time, we did not have the luxury or rewriting to use more asynchonous methods or to use a javascript framework, and so I was working with what I had.

I had an Accordion object that held a set of filters. These filters were set up much like you would see on — the filters in a left menu would control data in the main div of the page. The previous iteration had the user select all filters and then “apply” that to the data. The page would refresh and one would see the filtered data set. This approach created performance issues as multiple trips to the database and an entire reloading of the viewstate and session were initiated.

Not only did we want to improve performance, but we wanted to make it more “dynamic”, in that a user could choose a filter and it would not refresh the entire page, but rather would only refresh certain sections. For this we used update panels.

However, despite having the !IsPostback code in the appropriate places, I ran into an error. The error stated that I had a repeated control in the accordion.

This happened because I generated the accordion, which held the filters, server-side. It is generated once, at page initialization, with a call to the database, which returned filters based on the logged in user’s account permissions. When the user chose a filter, the set of filters was being appended on each postback, generating the error.

If you ever run into such a case, then the key for me was to simply set EnableViewState = false on the control itself. You may need to save the ViewState for other actions on the page, but conveniently enough you can target certain objects for which a ViewState is not retained. Once I did this, the new accordion filters were able to load on each post-back.

No, this was not the ideal solution, but it was acceptable in order to get the desired behavior. The generation of the accordion and filters was a legacy decision, and the web services that populated that accordion were coupled very tightly with the application code architecture. This is a great example of where you just have to tap into current patterns and “blend it in” and get it working. Technical debt is a real thing and it is important to be cognizant of that. A business must run and a good leader is able to weigh the pros and cons of taking a specific decision for both the short-term interests and long-term successes of the company.