Frank Wang's inspirations on .NET

IEnumerable<Inspiration> inspirations = from i in DataContext.Inspirations where i.Sharable == true select i

Enable Back button support in ASP.NET AJAX web sites

Wednesday, October 29, 2008 5:08 PM

An inherent problem with AJAX-style applications is browser navigation. AJAX pages don’t post back when performing requests tasks so they can’t remember their “previous states”. The problem comes when users click the browser's back button. What happens is browsers don’t return to a previous “state” of the page, instead, the browser unloads the page entirely and returns to the previous page. Technically speaking, this is OK because one may argue it’s just how AJAX works. However, a more user-friendly design needs to be able tackle this problem.

The ASP.NET AJAX Framework came with native support for back button and history management back in July 2007, when it was still called ASP.NET Futures. You would have to use a History control back then to achieve this goal. In the latest ASP.NET 3.5 release, the History control was removed from the framework, and all its functionality was ported into ScriptManager. Adding back button support to your AJAX page has become easier than ever. In today’s post, we will be looking at a typical “back button”: navigate in AJAX page with tabbed content. And then we will solve the problem by introducing the back button support.

Let’s start with creating a new ASP.NET web site in Visual Studio 2008. I named the web site TabbedContent. Go ahead and add a ScriptManager and a UpdatePanel to the default.aspx form. This will enable AJAX in our site. Now drop a TabContainer control inside the UpdatePanel. Note the TabContainer control was shipped with AJAX Control Toolkit. If you don’t have the toolkit installed, you can download it from CodePlex.  Once you have placed the TabContainer in the UpdatePanel, you can add a few TabPanel controls to it, and of course you can throw any content onto each TabPanel at your choice. If you want, you can copy and paste what I have in the TabContainer. I created three tabs, each for an auto maker, listing the models in a BulletList control.

<cc1:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0">
<cc1:TabPanel ID="tpAudi" runat="server" HeaderText="Audi">
    <ContentTemplate>
        <asp:BulletedList runat="server">
            <asp:ListItem>A4</asp:ListItem>
            <asp:ListItem>A5</asp:ListItem>
            <asp:ListItem>A6</asp:ListItem>
            <asp:ListItem>A8</asp:ListItem>
        </asp:BulletedList>
    </ContentTemplate>
</cc1:TabPanel>
<cc1:TabPanel ID="tpBMW" runat="server" HeaderText="BMW">
    <ContentTemplate>
        <asp:BulletedList ID="BulletedList1" runat="server">
            <asp:ListItem>335</asp:ListItem>
            <asp:ListItem>528</asp:ListItem>
            <asp:ListItem>745</asp:ListItem>
            <asp:ListItem>Z4</asp:ListItem>
        </asp:BulletedList>
    </ContentTemplate>
</cc1:TabPanel>
<cc1:TabPanel ID="tpMercedez" runat="server" HeaderText="Mercedez">
    <ContentTemplate>
        <asp:BulletedList ID="BulletedList2" runat="server">
            <asp:ListItem>CLK 500</asp:ListItem>
            <asp:ListItem>S 550</asp:ListItem>
            <asp:ListItem>E 350</asp:ListItem>
            <asp:ListItem>C 60 AMG</asp:ListItem>
        </asp:BulletedList>
    </ContentTemplate>
</cc1:TabPanel>
</cc1:TabContainer>

Now your web site should be complete.Go ahead and run it.

Audi BMW

As you can see, the AJAX page doesn't post back when I switch between the tabs. The back button is always disabled because everything stays on the same page. So you may be wondering what the problem is. Everything happens on one page with no page postbacks. Isn’t that great user experience? Well yes and no. Let’s introduce the problem by adding another page login.aspx. This page has nothing on it but a redirect link to default.aspx.

<form id="form1" runat="server">
    <div>
        <asp:HyperLink ID="hlDefault" runat="server" NavigateUrl="~/Default.aspx" Text="Go to default" />
    </div>
    </form>

 

 

 

Now set the login.aspx as the startup page and run the web site again. Click on “Go to default”. Note the browser’s back button becomes enabled when you get redirected to default.aspx from login.aspx.

image image

On the default.aspx page, switch to Mercedez from Audi, and then click the back button. Oops… what happened? Now you are on the login page again. Didn’t you want to go back to Audi from Mercedez? Imagine how annoying this can be for a car buyer who is comparing different brands. 

image image image

Now we are going to solve this problem by leveraging the new history feature in ScriptManager. The key thing here is have the browser remember the history points as we navigate in an AJAX page.

Step 1 – Enable history point in ScriptManager.

This is a new feature only available in ASP.NET 3.5 and later. It’s pretty simple. You just need to add EnableHistory=”true” to the ScriptManager on your page.

<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="true" 
/>

Step 2 – Store the current ActiveTabIndex property of the TabContainer control in ViewState. We will be using the stored value in a moment.

Place this code in your default.aspx code behind file.

protected int ActiveTabIndex
{
  get
  {
      return ViewState["ActiveTabIndex"] != null ? Convert.ToInt32(ViewState["ActiveTabIndex"]) : 0;
  }
  set
  {
      ViewState["ActiveTabIndex"] = value;
  }
}

Assign the initial value to ActiveTabIndex when default.aspx first loads.

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        ActiveTabIndex = 0;
    }
}

Step 3 – Wire up the TabContainer’s ActiveTabChanged event

protected void TabContainer1_ActiveTabChanged(object sender, EventArgs e)
{
   ActiveTabIndex = TabContainer1.ActiveTabIndex; // Update the ActiveTabIndex property
   ScriptManager1.AddHistoryPoint("ActiveTabIndex", ActiveTabIndex.ToString()); 
}

Every time the tab index is changed, we need to make sure the ScriptManager remembers the last “state” of the TabContainer. It’s important to set the AutoPostback property to true in order for the ActiveTabChanged event to be fired.

Step 4 – Wire up the ScriptManager’s Navigate event.

This event is raised during asynchronous postbacks automatically when the server-side history state changes.

<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="true" 
     onnavigate="ScriptManager1_Navigate" />

Our server-side code for navigation is very straightforward. All the history points were already stored during postbacks. Now we just need to retrieve the value and assign it to the TabContainer’s ActiveTabIndex property. The history points are represented by a NameValueCollection.

protected void ScriptManager1_Navigate(object sender, HistoryEventArgs e)
{
  TabContainer1.ActiveTabIndex = Convert.ToInt32(e.State["ActiveTabIndex"]);
}

With all the changes we have just made, we should be able to switch between the tabs by clicking on the back button. This is illustrated by the screen shots below.

image image  Goback imageimage

 

 

 

 

 

 

Finally, here’s the source code of the demonstration. Feel free to download it.




Feedback

# re: Enable Back button support in ASP.NET AJAX web sites

Nice tutorial for those using Ajax technology with Postbacks (kind of an oxymoron isn't it).

Picture this - an ajax tab container that get the markup for each tab from a web service. The desire would be to set history points from the client when the active tab changes. Unfortunately this is not possible. 11/6/2008 5:14 AM | John Nixon

# re: Enable Back button support in ASP.NET AJAX web sites

How do i make it work for ASP.net 2.0? 12/10/2008 11:34 AM | Srivani

# re: Enable Back button support in ASP.NET AJAX web sites

for 3.5 ok wat abt 2.0..

i am facing back button issue in asp.net 2.0 can u plz..

regards,
Kumar 2/16/2009 4:52 AM | kumar

# re: Enable Back button support in ASP.NET AJAX web sites

How would i make this work for a dropdownlist running inside of an update panel? Depending on what is picked in the list it changes the select parameter on a gridview container based on the control id. the only problem is going forward to a link inside that gridview and then pressing back brings it back to the original choice in the drop down list instead of the thing that was actually picked. Is this possible to fix? Thanks 7/29/2009 12:54 PM | aaron

# re: Enable Back button support in ASP.NET AJAX web sites

The only problem of storing history using script manager and then navigate back is, "IT WILL BREAK YOUR COMPONENTS IN THE MASTER PAGE, IF ITS IMPLEMENTING ICallbackEventHandler". And unfortunately I am still not able to solve it. Let me know if anybody has good solution. 9/14/2009 11:04 AM | Tushar Parekh

# re: Enable Back button support in ASP.NET AJAX web sites

When using a ScriptManager on a master page it is helpful to use a ScriptManagerProxy on your content page.

http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanagerproxy.aspx 10/7/2009 9:55 AM | Adam Roach

# re: Enable Back button support in ASP.NET AJAX web sites

im need to lerning ajax 5/20/2010 1:51 AM | salam

# re: Enable Back button support in ASP.NET AJAX web sites

Hi,

I think these two aattributes are not available for asp.net2.0,
EnableHistory="true" onnavigate="ScriptManager1_Navigate".

so how can i do that for asp.net2.0 C# Application. Please reply 6/7/2010 1:22 AM | venkat

# re: Enable Back button support in ASP.NET AJAX web sites

how can we achieve the same if we use linkbuttons in place of ajax tabcontainer 7/14/2010 9:38 AM | Manoranjan

# re: Enable Back button support in ASP.NET AJAX web sites

Doesn't work if I have button outside the UpdatePanel does a whole page postback, then click the browser Back button. 1/12/2012 3:49 PM | PG

Post a comment