Published: 17 Dec 2007
By: Dino Esposito

History points and back/forward navigation in ASP.NET Extensions 3.5

Just a few weeks after the release of the .NET Framework 3.5 and Visual Studio 2008 in mid November, Microsoft shipped the first CTP of a new toolkit for ASP.NET developers - the ASP.NET Extensions 3.5. The toolkit contains a selection of features that were already distributed as part of the latest ASP.NET Futures build, back in July 2007. The ASP.NET Extensions 3.5 will probably make its way into the Service Pack 1 of the .NET Framework 3.5 in late 2008. It is centered on a new version of the system.web.extensions assembly numbered as version 3.6.0.0.

ASP.NET Extensions 3.5 includes a new set of helper controls for Silverlight programming, as well as a new family of data-bound control (Data Dynamic controls). In addition, it brings to the masses a new build of ADO.NET Data Services (formerly, Astoria services) and the first binaries of the MVC framework.

In this article, though, I'll focus on yet another feature of ASP.NET Extensions 3.5 - the native support for history points and back/forward browser navigation.

The Different Nature of AJAX Pages

The essence of the AJAX revolution is all in the fact that now pages can be designed and authored to perform most of their tasks without making full postbacks to the server. The user interface of a given page remains up and running all the time, until it is explicitly dismissed by the user when he or she navigates to another page. What if the user wants to undo the latest action? Unless the Web application provides a made-to-measure model for rolling back certain operations, all that the user can do is move back to the previous page. On the other hand, the Back button of browsers exists just to let users go back to the previous state of the application. Likewise, the Forward button was designed to let users move onward from a previous page that they reached via the Back button. Normally, browsers supply a client-side programming model - the history object in the Browser Object Model (BOM) - for executing back and forward movements programmatically.

Regardless of the technology used to create it, an AJAX application tends to replace URL-to-URL browser navigation with script-driven HTTP requests. The history of an AJAX application doesn't necessarily coincide with the list of visited URLs. More likely, an AJAX history is a list of action points scattered through one or a few pages. In a nutshell, AJAX breaks the assumption that the previous state of a Web application coincides with the previously visited URL. This is a big change and can be seen as the offspring of the new paradigm that AJAX pushes for Web applications. The net effect is that all the user interaction with an AJAX page produces a single entry in the browser's history. Hence, when you click the Back button you are redirected to the previously visited distinct URL which may be an entirely new page even in a different application.

As of today, browsers do not provide in their BOM an API to add significant states of a page to the global browser history. Worse yet, browsers lack the notion of a save-point - that is, a significant state in the page lifetime that you want to store for returning later. Browsers only add URLs to their history, and only URLs that you have reached through the browser itself. With AJAX pages, instead, you often reach URLs using a distinct HTTP engine based on the XMLHttpRequest object. All of this navigation would be lost, unless the Web framework (i.e., ASP.NET Extensions 3.5) does some smart tricks.

The History Extensions to ASP.NET AJAX

It should be noted that the Web framework can't just replace the browser's history with its own engine. The issue is that you need the framework to do something that provides a new feature (page save-points) in the context of tools that only recognize URLs and, more, lack an API to extend the history list programmatically.

In ASP.NET Futures July 2007, Microsoft introduced a new server control for custom history management - the History control.

In ASP.NET Extensions 3.5, the History control has been removed. However, the functionality is now incorporated in the ScriptManager control. Here's the code you need in an ASP.NET AJAX page to track specific page states and save those states for later. Note that what I previously called a page save-point is referred to as a history-point in the ASP.NET Extensions 3.5 naming convention.

History support is disabled by default meaning that you need to set the property EnableHistory to true in order to enable it. The ScriptManager fires the Navigate server event whenever the user navigates to a URL that represents a previously saved page state. By handling the Navigate event, the developer takes control of the special page request and manages to bring the page back to the requested state. The history point, in fact, is an abstraction and doesn't match a physical page that the browser can autonomously render. The history point is bound to a fake URL created by the ScriptManager control. This fake URL is the original URL plus some user-defined state information. Let's delve deeper.

Adding History Points

When do you need a history point? Any server-side event is a potential history point. As mentioned, a history point refers to a state of the page that is significant for the page and the application. This state is so significant that you want to bookmark it for a future reference. A good example of a situation where you want to define history points is an ASP.NET wizard or a control with in-place editing capabilities such as a GridView or a DetailsView. More importantly, the server-side interface of history points work in the context of partial rendering applications based on the UpdatePanel control. For client-side programming, you can still use history points but leveraging a client JavaScript interface.

Consider a page with an UpdatePanel control wrapping a DetailsView and a SqlDataSource. The user may turn the DetailsView in edit or read-only mode and through the set of bound records. Here's an excerpt from the code-behind class of a sample page:

The AddHistoryPoint method on the script manager class creates an entry in the browser's history stack and makes it point to the page URL mangled with some extra data. In this case, the AddHistoryPoint method is invoked in PageIndexChanged and ModeChanged events. In other words, when the DetailsView changes its mode or displays a new record, a bookmark to the current state is added so that the user could navigate back there using the Back button.

The AddHistoryPoint method takes two arguments: the name of the parameter representing the state and the state value. Because this information is appended to the URL, you should manage to keep it quite cryptic and short. In the previous example, I'm using one letter to indicate "page" or "mode" followed by the concrete state information: the page index or the mode. This is arbitrary and should be adapted to the specific context.

The user then sees this page URLs added to the history list. Whenever one of these pages is reached, the Navigate event is fired. By handling this event in managed code, you restore the proper state acting on the properties of all involved controls. The following code moves the DetailsView to the specified page and restores the specified state as appropriate.

Note that in this example the ToInt32 is not a native method of the System.String class. It is rather a C# 3.0 extension method added to the sample project. It wraps the classic API to convert strings to numbers.

Summary

Lack of full control of the browser history is one of the key drawbacks of ASP.NET AJAX and AJAX in general. Although limited by the browser's support for Back and Forward buttons, the History API is powerful and generic enough to let you abstract history points and create bookmarks for them in code. We examined the server-side API. However, an equivalent API does exist also for the client side, but I will dig it out in the next article.

<<  Previous Article Continue reading and see our next or previous articles Next Article >>

About Dino Esposito

Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...

This author has published 54 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category


Code First Approach using Entity Framework 4.1, Inversion of Control, Unity Framework, Repository and Unit of Work Patterns, and MVC3 Razor View
A detailed introduction about the code first approach using Entity Framework 4.1, Inversion of Contr...
jQuery Mobile ListView
In this article, we're going to look at what JQuery Mobile uses to represent lists, and how capable ...
Exception Handling and .Net (A practical approach)
Error Handling has always been crucial for an application in a number of ways. It may affect the exe...
JQuery Mobile Widgets Overview
An overview of widgets in jQuery Mobile.
Book Review: SignalR: Real-time Application Development
A book review of SignalR by Simone.

You might also be interested in the following related blog posts


Visual Studio Add-In vs. Integration Package Part 1 read more
Implementing a WCF service firewall part II of N read more
Fluent Interfaces and Flowcharts read more
Multi-Value Key for a Dictionary read more
SQL SERVER - Few Useful DateTime Functions to Find Specific Dates read more
Impressive author lineup over at DotNetSlackers read more
EFExtensions and stored procs with shaped results read more
WCF - Syndication Extensions read more
Enable the back button in ASPxGridView - Experimental read more
Simple Sharing Extensions for .NET read more
Top
 
 
 

Discussion


Subject Author Date
placeholder Restoring other controls... Mike E 11/20/2009 11:07 AM
Wrong Category? Kazi Manzur Rashid 1/3/2008 9:27 AM
placeholder history enabled scriptmanager Alex Grach 1/29/2008 11:43 AM
VS2005 History support William Yeager 2/17/2008 2:27 PM

Please login to rate or to leave a comment.