views:

429

answers:

2

I use the Application_Error event to catch and log errors in my app. The Error is logged, then a friendly error screen is displayed:

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        Dim ex As New Exception( _
            String.Format("Error on page: '{0}'.", HttpContext.Current.Request.Url), _
            Server.GetLastError())

        Dim uid As Guid = Log.FatalError(ex)
        Server.Transfer(String.Concat("~\\GlobalError.aspx?error=", uid))
End Sub

In my web.config I have:

<customErrors mode="On" defaultRedirect="GlobalError.aspx">
  <error statusCode="404" redirect="PageNotFound.aspx" />
</customErrors>

Whenever a user tries to load a page that doesn't exist, they get the GlobalError.aspx page, not the PageNotFound.aspx page. I looked in the Application_Error event and found that the Response StatusCode was 200, while the Server's last error was "Page 'foo.aspx' was not found."

What do I need to do to get this working correctly?

A: 

To begin with, you'll have to decide why they're getting GlobalError.aspx. You've shown us two possibilities; maybe there are more.

Change the name of one of those entries to GlobalErrorX.aspx and see what happens.

John Saunders
When I remove the defaulRedirect, it pushes the user to the same place. Obviously the two references to the file are redundant.
Pete Michaud
I just realized that the 404 could mean it can't find the error page. Check the IIS log.
John Saunders
No, the 404 page comes up when it's loaded directly, and the log says foo.aspx isn't found.The issue is actually with some "clever" users. I use a page called bar.aspx. At the client site "bar" is called "foo". When they load bar.aspx they see a big title that says "Foo" -- it's just a difference in terms between various clients that we handle similarly to a language dictionary.The problem is that they try to load foo.aspx directly, and get an error screen which makes them think that foo.aspx is broken, when in fact the error just means foo.aspx doesn't exist like they think it does.
Pete Michaud
A: 

In the Application_Error function you should only Server.Transfer if the error isn't a page not found/404 error. In those cases leave it to ASP.NET to do the redirect using the settings in the web.config.

You could figure out if it's a 404 using the following:

Exception ex = Server.GetLastError();
if (ex.GetType() == typeof(HttpException))
{
  HttpException httpEx = (HttpException)ex;
  if(httpEx.GetHttpCode() == 404) {
    return;
  }
}
Server.Transfer("~/error.aspx");
Steve Temple
I thought about this, but like I said, even when the page isn't found, the StatusCode is 200, not 404.
Pete Michaud
I've added a snippet of code to detect if it's a 404 error
Steve Temple
This works as one would expect, but it seems clumsy, no? Why do I have to detect this? Why doesn't the web.config work the way I expect it to?
Pete Michaud
I think by dealing with it in the Application_Error function it doesn't then pass it on to the redirect specified in the web.config. When I've read the official documentation the Application_Error function does the logging and then the web.config does the redirecting to the friendly error message page. Of course then you don't have access to the error object so it's not easy to display something meaningful.
Steve Temple