I often see developers (myself included) get frustrated when Ajax and the browser back button don't play nice together. The fact is, they have never really worked together and having the ability to use one means you have to sacrifice the other. But what if you want both? Let's take a look at why in the past we have not been able to have these features together and what we can do now to get them.

Back in the "olden days" of the Internet each web page was a stateless, static entity. With the advent of new web frameworks like ASP.NET we are able to get state into our web sites and thus some new and cool functionality. More recently, Ajax has enabled us to create more responsive web applications that give the look and feel of a desktop application. These new "ajaxified" web apps offer unprecedented speed and interactivity, and can be run entirely within a single web page.

Thanks to the wonderful XmlHttpRequest object a pag can communicate asynchronously with the server behind the scenes and update the page when new content is returned. While this gives us the wonderful benefits we have come to love from Ajax, it also creates a headache when we want to use that traditional web-browsing feature, Mr. Back Button. Unfortunately, because a new page is never requested when we make an Ajax call to the server, the browser history is never updated. So what happens when I am smack-dab in the middle of using my favorite Ajax application and need to back up a few steps? I am out of luck. That browser back button is simply going to return me to the previous physical page I visited, not to point where I last interacted with the application.


History Support in the Framework

So how do we solve this problem? Well, luckily we don't have to worry about it too much because Microsoft is taking care of all the gory details for us in the forthcoming Service Pack 1 of .NET Framework v3.5. ASP.NET AJAX will offer additional functionality which gives us the ability to manually set History Points in our web application. This feature will allow developers to configure their applications so that users can return to a previous state of the app at any time. Previously this functionality was encapsulated in a separate History control, but has since moved to the ScriptManager control in the latest beta of the service pack. And since new stuff like this is always more fun to see in code, let's take a look at an example of how this can be accomplished.


ASP.NET AJAX History Demo

By way of an example, I've built a simple form which can be used to enter a person's contact information.

Img1

The form has 6 TextBox controls and one Button control, all of which are wrapped in an UpdatePanel so that we can asynchronously submit the contact information and receive only the updated portion of the form without having to retrieve a completely new page from the server. While this performance benefit may be trivial in such a small application, it can greatly enhance the round-trip time between browser and server in much larger applications. Additionally, this allows us to get rid of the ugly page flicker normally caused during a postback to the server.

To enable the history feature, we must first set the EnableHistory property of the ScriptManager control to true.

Img2

With history enabled in our page, we can now add History Points to our application. History Points can be thought of as snapshots of our application at a given point in time. You can add to a History Point any state information needed to accurately repopulate a page during navigation through the page's history. In this example, I added a History Point to the ScriptManager every time the Button's Click event is fired, which would indicate that a new contact has been submitted. Since this event changes the state of the application, it is a good idea to save the state of the page as that event is processed.

To add a History Point, simply call the AddHistoryPoint method on the ScriptManager control and pass it a NameValueCollection populated with all the state information you'd like to save. You can also optionally set the title of the page when calling AddHistoryPoint as well. I highly recommend this, as it will provide users with a more descriptive name in the history menu of the browser.

Img3

But how does this information get loaded back into the page when a user clicks the back button? Well, notice that in the ScriptManager we also configured it to handle the OnNavigate event. This event is fired when a user navigates to a previous point in the page's history. When handling the event, we simply retrieve the state information from the HistoryEventArgs object passed to the event handler, and then repopulate the page with the data it previously contained.

Img4

With this functionality configured on the page, we can now interact with the form and still maintain the browser history, thus enabling the back button and Ajax to play nicely together at last.

Img5


Thoughts on the History Feature

The new history feature helps solve the problem of allowing users to use the back button feature they expect while at the same time not sacrificing the rich functionality Ajax provides. I must admit the new history feature does have some drawbacks though. Whether or not these issues will be addressed before we see the official release remains to be seen. In the meantime, here are my gripes with the History control in its current state:

  • In IE, adding a History Point does not seem to work the first time. After adding two or more, everything works fine. But if I add one history point and then try to navigate back to it, my page simply goes back to its original state instead of to the state I saved. I did not experience this problem in FireFox.
  • The switch from the History control to the ScriptManager also included a switch from using a Dictionary<> to a NameValueCollection for saving state information. Since the NameValueCollection object only holds strings, I much prefer using the Dictionary<> for this. In the past I could simply wrap my data in serializable objects and save them to the dictionary. Now I have to convert each piece of data to a string and save/retrieve them individually.
  • Managing History Points can be complicated, and requires quite a bit of effort on the part of the developer. As you can see, for just this simple example I had to manually add every piece of data I wanted saved each time I added a History Point. This feel tedious and cumbersome, and would not scale well with larger applications.

Telerik and History Support

Adding history support in web applications that use the ASP.NET AJAX framework is important to Telerik, especially because our most popular suite of controls is built off of that framework. While we do offer history support out of the box in our RadAjax controls, it is rather limited and currently only works in IE. But don't fret! Since our RadControls are built on top of the ASP.NET AJAX framework, you can rest assured that our controls will work wonderfully with the built-in history support as Microsoft develops it further.


Other Resources

The addition of history support in the ASP.NET framework definitely adds some great functionality that has long been needed, and it is nice to know we have this feature to look forward to. There are some other great resources for learning how to use this feature, including this this article by Dino Esposito and this video tutorial by Bertrand Le Roy. Also, if you want to see a custom implementation of this feature, take a look at Nikhil Kothari's UpdateHistory control here.

You can download the source code from my example here. Please not that in order to use this example you must have .NET Framework 3.5 Service Pack 1 Beta installed on your machine.


Comments

Comments are disabled in preview mode.