views:

202

answers:

2

I have an ASP.NET page to handle "404 page not found" it's setup by configuring the <customErrors> section in my web.config file and setting the custom error page for 404 errors in IIS manager.

It works as expected for pages in the root of my website but doesn't work in a subdirectory of the site - the hyperlinks and content in my custom error page have the wrong url base.

All the links in my error page are server-side controls (runat="server") and have their links based with "~/".

When I browse the site with http://mysite/nosuchfolder/nosuchfile the page renders with links thinking it's being served from the root, rather from nosuchfolder and as such all the links are broken in the browser as the browser is basing links from nosuchfolder.

Is there any way to 'tell' the ASP.NET page to re-base links on a different folder/filename?

Notes:

  • The majority of the page template is rendered from a master page
  • I'm running IIS6 and have set custom error 404 to URL: /error404.aspx
  • In my web.config file I have configured the <customErrors> section to redirect to /error404.aspx
  • As a workaround I am using the HTML <base> tag in the page, but I want to avoid this
  • I don't want to have to change all my "~/" based links to "/" or an in-line basing hack
A: 

When you set uo yoru custome error pages, is it using redirection or URL rewriting? The problem you describe is a common issue when implementing URL rewriting in ASP.NET. Essentially, in URL rewriting it becomes unclear to the processor which URL to use when parsing URLs. A number if articles/posts have been written on how to address the issue.

http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx

http://searchengineland.com/url-rewriting-custom-error-pages-in-aspnet-20-12234

James Conigliaro
Thanks James, I'm not using any URL rewriting - just redirection in IIS and in my web.config. I'll read up those pages though
Alex
A: 

Scott Gu's article on URL rewriting put me on the right path (so to speak!) - thanks for the tip James.

The answer is to use Context.RewritePath(newPath)

Here is the code I use in my custom 404 page -

protected override void Render(HtmlTextWriter writer)
{
    string rebase = Server.UrlDecode(Request.ServerVariables["QUERY_STRING"]);

    if (rebase.Length>10 && rebase.StartsWith("404;"))
    {
        try
        {
            rebase = new Uri(rebase.Substring(4)).AbsolutePath;
        }
        catch
        {
            rebase = "/";
        }
        finally
        {
            Context.RewritePath(rebase);
        }
    }

    base.Render(writer);
    Response.StatusCode = 404;
}

To handle missing .aspx pages in the same way, there is a setting in web.config called redirectMode that you set to ResponseRewrite

<customErrors mode="On" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="~/error404.aspx" />
</customErrors>

This stops the default behaviour of redirecting the user to ~/error404.aspx?aspxerrorpath=badfile

Note: this setting is new to the latest ASP.NET service packs (e.g. Framework 3.5 SP1)

MSDN Reference for redirectMode

Alex