Fog Creek Software
Discussion Board




Welcome! and rules

Joel on Software

How to determine previous page URL in ASP.NET

I have a web page that can be reached from more than one page in my site.  After clicking a Save button, I want to return to the previous page.

I know that I can get the referring URL and save it in a session variable:

Session("LastPage") = Module1.GetLastPage(Request.UrlReferrer.ToString)

(GetLastPage returns only the pageName.aspx portion of the URL)

It appears that upon postback, the Request.URLReferrer contains the URL of the current page.

Is there something else in the .NET framework that provides this information?

Jason Watts
Wednesday, May 28, 2003

Here's approximately how we do this. Basically, you 'stash' the referrer url away somewhere on the page's first view. You can use ViewState or a custom hidden field.

void Page_Load(...)
{
  if( !IsPostBack )
  {
    ViewState["ReferrerUrl"]  = Request.UrlReferrer.ToString()
  }
}

void returnToSender()
{
  object referrer = ViewState["ReferrerUrl"];
  if(referrer != null)
      Response.Redirect((string)referrer);
  else
      Response.Redirect("Default.aspx");
}

Duncan Smart
Thursday, May 29, 2003

That points me in the right direction. Thank you.

I had not known you could use the ViewState for storing objects.  Is there an advantage to using ViewState as opposed to Session variables?

Jason Watts
Thursday, May 29, 2003

ViewState is just for mainitaining state for an individual page through postbacks. Session is for stuff you want to last longer than that -- ie, when they browse to another page in your app.

Anything that is either Serializable or has a TypeConverter can be stored in ViewState http://msdn.microsoft.com/library/en-us/cpguide/html/cpconmantainingstateincontrol.asp

Duncan Smart
Thursday, May 29, 2003

Bear in mind that there is a penalty for this convenience; namely, that the viewstate delta is transmitted as a hidden field which is Base64 encoded XML. If you abuse it, it can grow to ridiculous sizes.

We test drove some 3rd party ASP.NET controls which seemed very sluggish. We discovered why with a quick View Source: one example generated 2MB of HTML, of which 800K was the viewstate.

Tread lightly. :)

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

Do you actually have your ReturnToSender funtion in each code behind file?  I attempted placing this in an external module, but cannot find where to access the ViewState object.

Jason Watts
Thursday, May 29, 2003

The ViewState property is "protected" menaing you can only (easily) get to it from a subclass. So instead of having your pages derive from System.Web.UI.Page directly, have them derive from your own base class which implements a ReturnToReferrer method or something (as well as other useful stuff).

In fact, we don't use ViewState due to the things mentioned by Brad, but instead stash this sort of stuff stuff "manually" using RegisterHiddenField (ViewState is disabled for the entire page rather than disable on a control by control basis).

Bear in mind that ViewState offers optional encryption and signing of the payload though - so you pays your money...

Duncan Smart
Thursday, May 29, 2003

If you don't want to go the page-derivation route, just change the mechanics of the method slightly:

void returnToSender(string url)
{
  if(url != null)
    HttpContext.Current.Response.Redirect(url);
  else
    HttpContext.Current.Response.Redirect("Default.aspx");
}

Then call it from your page, like so:

  returnToSender(ViewState["ReferrerUrl"] as string);

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

Oh, and as to why you have to access ViewState from the page: it's hierarchal. The contents of the ViewState property bag are dependent on where you are in the control tree. This helps eliminate the need for unique viewstate IDs, because each is implicitly prefixed by the control's ID internally.

No such restrictions for Response, as you saw from my code.

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

Thank you both for the lesson in state management. 

Since Viewstate seems to be an appropriate place to store something as simple as a URL, I chose the path of subclassing the page object.  This solved my problem indirectly by allowing me to have ReturnToSender declared as a Friend function.

I did experiment with the RegisterHiddenField function, but after 20 minutes on MSDN, I was unable to figure out how to retreive the data back.  Perhaps I will revisit this at a later date.

Thanks again!

Jason Watts
Thursday, May 29, 2003

The data comes back as form data. Should be as simple as:

  Request.Form["fieldname"]

which should return a string.

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, May 29, 2003

I consider my original query to be more than adequately answered.  Here are the results of you patient tutoring from the actual working class file.

-- begin code snippet --
'Usage:   
'      Public Class EventEdit
'          Inherits EOBWeb.BetterPage
'         
'          Private sub Page_Load(byval s as object, _
'                                byval e as eventargs)
'              'your code goes here
'
'              If not IsPostBack SaveReferrerURL()
'          End Sub
'
'          private sub btnSave_click(byval s as object, _
'                                    byval e as eventargs)
'              'code to process changes
'              ReturnToPreviousPage
'          end sub
'      End Class

Imports System.Web.UI

Public Class BetterPage

    Inherits System.Web.UI.Page

    'Prevent more than one read of view state property
    Private _url As String

    Public Sub SaveReferrerURL()
        'Purpose:  Stores entire URL in view state

        ViewState("URL") = Request.UrlReferrer.ToString
        _url = viewstate("URL")
    End Sub

    Public Function ReferrerURLPageOnly()
        'Purpose:  Returns only the aspx pagename portion
        '                of the URL, i.e. "default.aspx"
        'Usage:      Select case ReferrerURLPageOnly
        '                  case "Events.aspx"
        '                  case "Sites.aspx"
        '                end select

        Dim pages As Array
        pages = _url.Split("/")
        Return pages(pages.GetUpperBound(0))
    End Function

    Public Function ReferrerURL() As String
        Return _url
    End Function

    Friend Sub ReturnToPreviousPage()
        If _url <> "" Then
            Response.Redirect(_url)
        Else
            Response.Redirect("Default.aspx")
        End If
    End Sub

End Class
-- end code snippet --

Jason Watts
Friday, May 30, 2003

I would add something like (my VB is a bit rusty):

Sub BetterPage_OnLoad(...) Handles OnLoad [??]
  SaveReferrerURL()
End Sub

...so the save is automatically done for you.

Also, just a thought, you might want to familiarise yourself with the System.Uri class for parsing URLs as you are in ReferrerURLPageOnly.

Duncan Smart
Friday, May 30, 2003

Sorry - I meant:

Sub BetterPage_OnLoad(...) Handles OnLoad
  If Not IsPostBack Then SaveReferrerURL()
End Sub

i.e get the base class (BetterPage) to do this work rather than having to repeat it in each class that derives from it

Duncan Smart
Friday, May 30, 2003

Aah!  I  had not realized I could name the proc something other than Page_Load.  Now all my repetitive code has been removed.

Thanks Duncan.

Jason Watts
Friday, May 30, 2003

*  Recent Topics

*  Fog Creek Home