Getting Rid of the Back Button Problem

A web browser's back button is essential for users to navigate across different web sites and web pages. However, for certain data sensitive web applications, using a web browser's back button can have unexpected and undesirable results. With poor planning, it could even crash a web site.

Take the following scenario as an example:

You developed a web survey for users to complete. Once the survey is submitted, the response is recorded in a database with a pre-coded caseID. Now, suppose a user just submitted his survey, then for some reason, he hit the browser's back button. Then, with or without making any changes, he submitted the survey again. Here, you ended up with two records (duplicate or not) with the same caseID. If the caseID is set to be unique, the user would get an error message.

In fact, the back button problem has pestered programmers for so long and caused so many headaches that across the net there is a flurry of questions, such as "How do I disable a browser's back button?".

Unfortunately, it is not possible to disable a browser's back button. Nor is it a good idea to do so. However, viable and simple solutions to get rid of this annoyance do exist.

The following is how you code it in a Class ASP way:

<%
   Response.Buffer = True
   Response.ExpiresAbsolute = Now() - 1
   Response.Expires = 0
   Response.CacheControl = "no-cache"
%>

This code snippet basically directs the page in concern to expire immediately once it is posted and set the page to cache none of its content. In ASP .NET, you can do something similar to disable browser page caching, like the following:

   Response.Cache.SetCacheability(HttpCacheability.NoCache);
   Response.Cache.SetExpires(Now.AddSeconds(-1));
   Response.Cache.SetNoStore();
   Response.AppendHeader("Pragma", "no-cache");

You can place the code in the page_load event. Ideally, the code should be executed whenever the page is loaded. And, whenever a user tries to go back to the page, he/she should get a "Page has Expired" warning.

However, some browsers may ignore the page cache settings and some users may still get away with submitting a form multiple times. This leads us to a second, more reliable solution: the timestamp solution. You should always use this solution while also adding the response caching instructions to the Page_Load procedure.

Here is the code showing you how:

   protected void Page_Load(object sender, EventArgs e)
   {
      Response.Cache.SetCacheability(HttpCacheability.NoCache);
      Response.Cache.SetExpires(Now.AddSeconds(-1));
      Response.Cache.SetNoStore();
      Response.AppendHeader("Pragma", "no-cache");

      if (Page.IsPostBack){
            if (isPageExpired()){
               Response.Redirect("expired.htm");
            }
            else {
               Session("TimeStamp") = Now.ToString;
               ViewState("TimeStamp") = Now.ToString;
            }
      }
      //...........
      //your own function here
   }

      private boolean isPageExpired()
      {
         if (Session("TimeStamp") == null ||
            ViewState("TimeStamp") == null)
            return false;
         else if (Session("TimeStamp") == ViewState("TimeStamp"))
            return true;
         else
            return false;
      }

The code is pretty self-explanatory. Whenever a page is loaded, it checks whether it is a resubmitted one by calling the isPageExpired function. If the function returns true, it redirects the page to the page-expired response; if not, it sets two timestamps: one saved in session state, the other view state.

The isPageExpired function compares the timestamp saved in session state and the timestamp in viewstate. If they are different, the user has submitted a form from cache; then, the page directs them to the Page-expired response.

So here it is, two simple solutions to the back-button problem. If you have other solutions or suggestions, please send me a comment. Thank you.



About the Author

Xun Ding

I have been working as a web developer for almost five years. Love various aspects of .NET, love this business of programming. Always want to learn more.

Comments

  • wheloltabotly PumeSonee Phobereurce 9172469

    Posted by TizefaTaNaday on 06/14/2013 12:46am

    Nitfranna airjordanretro3.holidaygiving.org Vovedeene airjordaniiiblackcement2011retro.holidaygiving.org Opedundicipse

    Reply
  • sdsds

    Posted by Nitya Guptacha on 04/09/2013 02:00am

    . The snippet "else if ViewState == Session" should return false, not true like you currently have. If these two values are different it means a post was just done. After a post is done, the Session value will still contain the timestamp, but the ViewState variable will not. That being said, the closing else statement should return true. And finally, if we fall into the statement "If(Page.IsPostBack)" and we do all these checks, wouldn't we also want to run our code within that postback statement as long as the page isn

    Reply
  • Amateur Programmer

    Posted by Joaquin on 08/10/2012 10:35am

    Firstly I want to thank you Xun Ding for his post: it has put me on the way to solve the horrid browser Back button issue I had. I had been trying to resolve it for months and now I've been able to implement a solution based on this post. That being said, I completely agree with Sam's post. In fact, I had done the very same changes he suggest before reading his post. However, for my solution to work (that is, redirecting the user to a customized page every time they click the "Back" button, I have had to remove the first line of the function isPageExpired: if (Session("TimeStamp") == null || ViewState("TimeStamp") == null) return false; I can't understand why is there. Finally, every time the user hit a control in the page which redirects them to another page (ie., button), you should reset to null the value of Session("TimeStamp"). If not, the will end in the expired.htm page. Hope this helps someone as this post helped me.

    Reply
  • Software Engineer

    Posted by Sam on 05/15/2012 02:02pm

    Correct me if I'm wrong, but won't the "Now.ToString" for the Session timestamp be slightly different than the "Now.ToString" in the ViewState timestamp? I believe a simple way to ensure they're exactly identical is to assign Now.ToString to a variable that both Session and ViewState will use, like so: String timeNow = Now.ToString Session["TimeStamp"] = timeNow; ViewState["TimeStamp"] = timeNow; I say this because otherwise the "Now.ToString" function will be called on two separate occasions and will return two different times. Also, your code contradicts your statement: "If they are different, the user has submitted a form from cache; then, the page directs them to the Page-expired response". The snippet "else if ViewState == Session" should return false, not true like you currently have. If these two values are different it means a post was just done. After a post is done, the Session value will still contain the timestamp, but the ViewState variable will not. That being said, the closing else statement should return true. And finally, if we fall into the statement "If(Page.IsPostBack)" and we do all these checks, wouldn't we also want to run our code within that postback statement as long as the page isn't expired? As it stands now your code during a postback will do nothing but redirect or set timestamps. I enjoyed the article though, it got me thinking! Thanks, keep it up.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Download the Information Governance Survey Benchmark Report to gain insights that can help you further establish business value in your Records and Information Management (RIM) program and across your entire organization. Discover how your peers in the industry are dealing with this evolving information lifecycle management environment and uncover key insights such as: 87% of organizations surveyed have a RIM program in place 8% measure compliance 64% cannot get employees to "let go" of information for …

  • It's time high-level executives and IT compliance officers recognize and acknowledge the danger of malicious insiders, an increased attack surface and the potential for breaches caused by employee error or negligence. See why there is extra emphasis on insider threats.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds