CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Peter's Gekko

public Blog MyNotepad : Imho { }

A back button for asp.net pages

For my app I needed a back button. Internet explorer and other browsers have back buttons, most mice have them as well but I needed my own small link to drop on my forms. Implementing it was no big deal, given you consider one essential quirk. After browsing around on the web I consider it worthwhile to share my findings.

The essential thing is what back really stands for. When an user is working with an aspx page she will regularly post back to the page leading to many renderings of the same url. By default back is back to the previous request. An application like Community Server (which is an asp.net app) works this way. Write you comment and click submit. When you click the back button of your mouse after that you'll be back editing the comment. When you click submit again it might look like you 're posting an updated comment. In reality CS does receive a new comment. (Don't try this at home, to prevent comment spamming CS blocks posting comments in that pace). To give the user a better user experience the smartNavigation property of an asp.net webform comes to the help. Setting it to true will redirect the user to the previous page when the back button is clicked. It does this by some script magic. Alas smartNavigation can play some nasty tricks on you when you try to redirect from a page which has it enabled.

In code you can see from which url the user came in the UrlReferrer property of the Request.. This always show the url of the last roundtrip, whether smartNavigation is switched on or off. So it will be the url of the page itself on a postback. On the first rendering of the page it will contain the intended page the user came from. So checking postback in combination with the referrer should do to find the desired url. The url has to be stored over roundtrips. On the best example I found on the web, by master of mystery Juval Löwy, it is stored in the session. This is a full demo ((free) registration required) where clicking a linkbutton performs a redirect to an URL. But besides problems with  smartnavigation I think the viewstate would be a better place to store the url than the session.

I use a plain HyperLink. The essence of my back link boils down to

private void Page_Load(object sender, System.EventArgs e)
{
   if (! IsPostBack)
      HyperLink1.NavigateUrl = Request.UrlReferrer.AbsoluteUri;
}
 

The NavigateUrl is set on the first request and will be saved over roundtrips in the viewstate.

As I am a bad and a lazy typist I don't want to code these lines again and again. Let's make it a custom control. Take these steps:

  • Add a new project, a Web ControlLibrary
  • Delete the webusercontrol1
  • Add a new item to the library, a Web Custom Control. Give it a real name
  • Delete all generated implementation code
  • Copy in this code
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace ButonBacklLibrary
{
    /// <summary>
    /// Summary description for MyBackButton.
    /// </summary>
    [ToolboxData("<{0}:MyBackButton runat=server></{0}:MyBackButton>")]
    public class MyBackButton : System.Web.UI.WebControls.HyperLink
    {
        protected override void OnLoad(EventArgs e)
        {
            if (! Page.IsPostBack)
                base.NavigateUrl = Page.Request.UrlReferrer.AbsoluteUri;
            base.OnLoad (e);
        }

        [Browsable(false)]
        public new string NavigateUrl
        {
            get
            {
                return base.NavigateUrl;
            }
        }
    }
}
 

The MyBackButton inherits from the HyperLink control. In the overriden OnLoad method the code to get the referral url is executed and stored in the NavigateURL property of the base, HyperLink, class. It no longer makes sense to manipulate the NavigateURL property of the back control in the designer or from code. I cannot override the property as it is not virtual. Using the new keyword the original property is shadowed. In code and in the designer my version of the property named NavigateURL is used. The implementation of the property can still get to the inherited property. The property getter just reads the base property, but the setter property has gone. I can no longer change the URL from code. By setting the [Browsable(false)] attribute on the property it will also be gone from the property window in the designer.

To get this button into the VS toolbox:

  • Right click the toolbox
  • Choose Add/Remove items
  • In the dialog click the browse button
  • Select the library we just built It's the dll in the bin\debug or bin\release directory
  • The control will show up in the toolbox.

You can start using the control in you project. Debugging works well, breakpoints set in the control's source will be hit.

Now you have a back button which is independent of the smartNavigation and session settings. But it does need the viewstate. Fiddling with that is another story.


Published Jul 19 2005, 04:28 AM by pvanooijen
Filed under:

Comments

Geoff Appleby said:

Are you using this for an internet facing public app?

Be careful of using the referrer if you are - there's a lot of proxies out there that silently remove the http referrer request header, so by the time the request is received, there's no referrer available to get a URL out of.

Other than that, very cool :)
# July 19, 2005 8:07 PM

pvanooijen said:

thanks Geoff.

In case the referrer is gone from the header it's no better than the normal back button. Where you see the same thing happening. As it's a custom control you could give it default back page, like the app's home.
# July 20, 2005 1:59 AM

Chi Wai Man said:

I found a nice article about a back button in ASP.NET: http://codebetter.com/blogs/peter.van.ooijen/archive/2005/07/19/129384.aspx...
# August 12, 2005 8:39 AM

Chi Wai Man said:

I found a nice article about a back button in ASP.NET: http://codebetter.com/blogs/peter.van.ooijen/archive/2005/07/19/129384.aspx...
# August 12, 2005 8:41 AM

Chi Wai Man said:

I found am article about a back button in ASP.NET: http://codebetter.com/blogs/peter.van.ooijen/archive/2005/07/19/129384.aspx...
# August 12, 2005 8:50 AM

Chi Wai Man said:

I found am article about a back button in ASP.NET: http://codebetter.com/blogs/peter.van.ooijen/archive/2005/07/19/129384.aspx...
# August 12, 2005 9:00 AM

Chi Wai Man said:

I found am article about a back button in ASP.NET: http://codebetter.com/blogs/peter.van.ooijen/archive/2005/07/19/129384.aspx...
# August 12, 2005 9:18 AM

Joe said:

I get following error while trying this:

Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:


Line 145:
Line 146: if (!IsPostBack)
Line 147: HyperLink1.NavigateUrl = Page.Request.UrlReferrer.AbsoluteUri;

# September 13, 2005 5:56 PM

Peter's Gekko said:

This is a question I often get. I'm a C# guy but that is just a matter of personal preference. It's the...
# October 6, 2005 5:32 AM

Peter's Gekko said:

SmartNavigation is a feature which can cause quite a lot of trouble. It is a property of an asp.net webpage...
# January 11, 2006 7:28 AM

Don Hesse said:

I think I see two issues with the code for the back button. I'm hoping that I'm wrong, so please let me know if I am.
1. I've found that at least one anti-spyware software (Norton 2005) strips the UrlReferrer information, making UrlRefferer = null.
2. You should probably add a test to see if the UrlRefferer is null before setting another object to it - just in case of #1.
Thanks. I'm hoping you know of a work around.
# January 24, 2006 7:10 AM

pvanooijen said:

When the refrerrer is gone it's gone. Nothing you can do about that. Like Geoff said in the fisrt comment.
The browser's back button will also be disabled. What the control could do is set its enabled state to false when there's no referrer.

if (! Page.IsPostBack)
{
if (Page.Request.UrlReferrer == null)
this.enabled = false;
else
base.NavigateUrl = Page.Request.UrlReferrer.AbsoluteUri;
}

Concerning Norton : These utilities mess up such an enormous amount of things I can only advise to stop using them. There are a lot of alternatives which do work and do not have the side-effects.
# January 24, 2006 7:52 AM

Peter's Gekko said:

Your browser has a back, forward and refresh button. Some time ago I wrote a little post on a back button...
# May 18, 2006 4:41 AM

Peter's Gekko said:

Yesterday I wrote a little post on a refresh button for asp.net pages. It worked but had jump through...
# May 19, 2006 3:56 AM

Mako said:

Tried this and it didn't work. Page.Request.UrlReferrer.AbsoluteUri doesn't exist, regardless of the history before I arrive at my page.

Why oh why is a back button in .NET so frigging HARD?

Why oh why do moronic users demand back buttons when there's already one THERE?

# September 18, 2006 11:34 PM

pvanooijen said:

Like some other comments state: several AV packages strip this property from the HTTP request. Nothing you can do about that.

And don't get me started on smartnavigation (just search my blog on it:))

Your back button has to be better than the browser's one, it should take the user a page back, and not a roundtrip (ispostback). Not all brwoser see this difference.

# September 19, 2006 2:29 AM

momobnj said:

Didn't work for me, either.  I have a search page, with a gridview showing search criteria (from text boxes) results.  When I click a link inside the gridview, I want to return to the gridview page from the linked page, but all I get is the original search page in its initial state, with nothing in the text boxes and no gridview.  Any suggestions for returning to the gridview with its intact search criteria?

Thanks in advance.  Can't tell you how frustrating this is.

# November 20, 2006 2:27 PM

momobnj said:

Clarification: I click a link inside the gridview, which takes me to another page.  I want to return from that page to the gridview page with the search stuff.

And no, I don't want to have the linked info on the same page in another gridview or details view; I want to keep them separate.

# November 20, 2006 2:29 PM

pvanooijen said:

I think you should restore the selectedindex of the gridview. Store that somewhere (session/cookie ?) and set it in the page load when returning to the page.

# November 20, 2006 3:03 PM

Namrata said:

I wish to know can we freeze the back button of the web browser we are using. If so please help me soon as I'm new to the coding world.

# May 8, 2008 7:24 AM

pvanooijen said:

The back button is part of your browser and hard, if not impossible, to reach from your code.. Every browser is different and besides that many a mouse or keyboard has a back button as well.

It's a better strategy to make your webapp behave well when the back button is fired. Check the smartnavigation settin gin the web.config

# May 13, 2008 3:47 AM

Joel said:

This works fine for hyperlink in asp.net but for Sharepoint Toolbarbutton Navigateurl looked also fine as i tested with f5 in page and all until i have problems if i just click in the url bar and type enter, like going again to the same page there:

Object reference not set to an instance of an object

Heres the page load code

   protected void Page_Load(object sender, EventArgs e)

   {        

       if (!Page.IsPostBack)

       {

               toolbarbutton1.NavigateUrl = Page.Request.UrlReferrer.AbsoluteUri;

           }

   }

what i am doing wrong here? Or this is not a good option for sharepoint controls?Thanks

# May 14, 2008 9:13 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!

This Blog

Syndication

News