Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET UpdatePanel: Make browser "back" button return to *last* version of the page

I have page A and page B. You can do the following things in page A:

  • Do stuff on page A (e.g., choose an item in a list box), which causes an UpdatePanel in page A to be redrawn with additional information.
  • Move on to page B. This is done with a Button and Response.Redirect.

Now the problem is as follows:

  1. The user does stuff on page A. Page A is now different from its initial state.
  2. The user moves to page B.
  3. The user hits the back button of the browser.

What happens: Page A in its initial state is shown.
What I would like to happen: Page A in its final state is shown (i.e., with the "correct" item selected in the list box).

I know about ScriptManager.AddHistoryPoint! As far as I can see, it does not solve my problem:

  • I could call AddHistoryPoint every time something is done on page A. This is bad, because it litters the browser history with lots of entries. (A new entry every time a different list box item is selected.) But that's exactly what I want to avoid by using an UpdatePanel! Of course, if there were a ReplaceLastHistoryPoint method, that would be perfect, but I did not find one...

  • I tried to call AddHistoryPoint right before Response.Redirect, to save only the last state of page A, but, alas, that doesn't work (no history point is saved). This is not surprising, considering how Response.Redirect works.

Is there some solution I have missed? I'm using .NET 3.5SP1, in case it matters.

like image 354
Heinzi Avatar asked Dec 20 '12 15:12

Heinzi


2 Answers

This is a bit of an old question, but I'll go ahead and provide the mechanism I use for this. The basic idea is that instead of allowing AddHistoryPoint to manage your name-value pairs, just allow it to manage a key to your NameValueCollection that you keep somewhere else, like in your Session cache. Then as subsequent Ajax requests come in, you never make another call to AddHistoryPoint; instead, you just replace your NameValueCollection with the state of the current request.

The only other bit is to keep track of whether you're on your first Ajax call and need to make that first call to AddHistoryPoint or not.

My code looks something like this:

  protected void Page_LoadComplete(object sender, EventArgs e) {
     if (!ScriptManager.GetCurrent(this).IsNavigating && (IsCallback || IsInAsyncPostback())) {
        var state=new NameValueCollection();
        //OnCallbackHistory(state); // this gets state for all interested parties
        if (state.Count != 0) {
           string key=ViewState["HistoryStateKey"] as string;   // empty on first AJAX call
           if (string.IsNullOrEmpty(key) || ScriptManager.GetCurrent(this).EnableHistory) {
              key=CallbackHistoryKeyRoot+Interlocked.Increment(ref callbackHashKey).ToString();
              ViewState["HistoryStateKey"]=key;
              ScriptManager.GetCurrent(this).AddHistoryPoint("", key);
           }
           Session[key]=state;
        }
     }
  }
like image 67
Kevin Donn Avatar answered Sep 21 '22 15:09

Kevin Donn


Instead of calling AddHistoryPoint on the server you could call addHistoryPoint on the client using the Sys.Application class, http://msdn.microsoft.com/en-us/library/vstudio/cc488025(v=vs.90).aspx.

So you'd add a client side click listener to the button which would addHistoryPoint on the client before the button does the post back and redirect.

like image 28
graham mendick Avatar answered Sep 22 '22 15:09

graham mendick