Sunday, February 13, 2011

404 page that displays requested page

I recently migrated a website to a new CMS (Umbraco). A lot of the links have changed, but they can be easily corrected by searching for patters in the url, so I would like to write something that will redirect to the correct page if the old one is not found. That part isn't a problem.

How can I obtain the requested URL after the browser is redirected to my custom 404 page. I tried using:

request.ServerVariables("HTTP_REFERER") 'sorry i corrected the typo from system to server.

But that didn't work.

Any Ideas?

The site is on IIS 6.0. We did consider using 301 redirects, but we don't have any way of knowing what pages people have bookmarked and there are a few hundred pages, so no one is keen on spending the time to create the 301's.

  • Update, you actually want to pick up:

    Request.QueryString("aspxerrorpath")
    
    From Kev
  • How about:

    Request.ServerVariables("HTTP_REFERER");
    
    Gthompson83 : Sorry that was a typo. I am using ServerVariables
    From LordHits
  • A lot of the links have changed, but they can be easily corrected by searching for patters in the url

    Rather than send your users to a 404, have you considered using url re-writes? This way your users (and search engines, if that's important to you in this case) will get a 301 or 302 rather than having to go through your 404 handler. It's usually quicker and less stressful on your servers to handle the rewrite at the url level than firing up your code and processing it there.

    Microsoft have released a URL Rewrite Module for IIS 7, and there's a decent introduction to it here and here.

    For IIS 6, there's a good intro here to getting URL rewriting working with it, slightly different than IIS7.

    An example rewrite rule would be

    # $1 will contain the contents of (.*) - everything after new-dir/
    RewriteRule /new-dir/(.*) /find_old_page.asp?code=$1
    

    there are a few hundred pages, so no one is keen on spending the time to create the 301's

    The beauty of rewrite rules is that you don't need to list to explicitly list all of your pages, but can write rules which follow the same pattern. We had to do something similar to this recently, and it's surprising how many of the moved urls could be handled by a couple of simple rules.

    From ConroyP
  • Instead of using a 404 page, I think the proper thing to do would be to redirect with a 301 - Moved Permanently code.

    Gthompson83 : I realize this is kind of a hack, but the client already launched the website and we are looking for a quick fix to the situation. They don't want to dedicate someone for the next day or so to create a few hundred redirects.
    Rich Bradshaw : You don't have to make them manually, just do them using an URL rewrite.
    From Neall
  • I do basically the same thing you ask in a custom 404 error handling page. On IIS 6 the original URL is in the query string. The code below shows how to grab the original URL and then forward the user. In my case I switched from old ASP to new ASP.NET, so all the .asp pages had to be forwarded to .aspx pages. Also, some URLs changed so I look for keywords in the old URL and forward.

    //did the error go to a .ASP page?  If so, append x (for .aspx) and 
    //issue a 301 permanently moved
    //when we get an error, the querystring will be "404;<complete original URL>"
    string targetPage = Request.RawUrl.Substring(Request.FilePath.Length);
    
    if((null == targetPage) || (targetPage.Length == 0))
        targetPage = "[home page]";
    else
    {
         //find the original URL
        if(targetPage[0] == '?')
        {
         if(-1 != targetPage.IndexOf("?aspxerrorpath="))
              targetPage = targetPage.Substring(15); // ?aspxerrorpath=
         else
              targetPage = targetPage.Substring(5); // ?404;
         }
         else
         {
              if(-1 != targetPage.IndexOf("errorpath="))
           targetPage = targetPage.Substring(14); // aspxerrorpath=
              else
          targetPage = targetPage.Substring(4); // 404;
         }
        }    
    
        string upperTarget = targetPage.ToUpper();
        if((-1 == upperTarget.IndexOf(".ASPX")) && (-1 != upperTarget.IndexOf(".ASP")))
        {
         //this is a request for an .ASP page - permanently redirect to .aspx
         targetPage = upperTarget.Replace(".ASP", ".ASPX");
         //issue 301 redirect
         Response.Status = "301 Moved Permanently"; 
         Response.AddHeader("Location",targetPage);
         Response.End();
        }
    
        if(-1 != upperTarget.IndexOf("ORDER"))
        {
                    //going to old order page -- forward to new page
                   Response.Redirect(WebRoot + "/order.aspx");
               Response.End();
        }
    
    From DougN
  • Here's what we do on init on our 404 pages:

    Dim AttemptedUrl As String = Request.QueryString("aspxerrorpath")
    If Len(AttemptedUrl) = 0 Then AttemptedUrl = Request.Url.Query
    AttemptedUrl = LCase(AttemptedUrl)
    CheckForRedirects(AttemptedUrl)
    

    CheckforRedirects then has custom logic to match up old URLs with new URLs.

    I'd argue that this is the preferred approach (as opposed to 301s or URL rewriting) if you have enough information internally to match up a large number of URLs from the old system with the new system - e.g. if you have a table that matches up old IDs with new IDs or something similar.

    If there's a consistent pattern that you can use to map old URLs to new URLs with a regex, though, then URL rewriting would be the way to go.

  • To build on the Rewrites suggestion, Umbraco already uses UrlRewriting.NET and new rewrites can be added to

    \config\UrlRewriting.config
    

    Hope this helps

0 comments:

Post a Comment