To properly handle custom errors in ASP.NET, it's essential to avoid using the web.config customErrors element.
The major drawback of using web.config customErrors is that it redirects when displaying custom error pages:
http://www.example.com/error/error.htm?aspxerrorpath=/somepage/p/12345.html
This creates two issues:
1. Users reporting problems will provide the redirected URL instead of the original one.
2. Users cannot refresh their browser to retry, or refresh after the issue is resolved to return to normal functionality.
The optimal solution we've implemented is handling errors in the Application_Error method of Global.asax.cs.
Here's the implementation:
protected void Application_Error(Object sender, EventArgs e)
{
Exception lastError = Server.GetLastError();
if (lastError != null)
{
if (lastError is HttpException)
{
if (((HttpException)lastError).ErrorCode == 404)
{
Response.StatusCode = 404;
Server.ClearError();
return;
}
}
ApplicationLogger.LogError("Application_Error", lastError);
Response.StatusCode = 500;
Server.ClearError();
}
}
Since we've specified custom error pages for 404/500 errors in IIS, we only need to return the appropriate status code (requires IIS 7.0 or later).
This approach also allows us to easily log errors to log4net before displaying custom error pages.
It's crucial to always call Server.ClearError(), otherwise ASP.NET will continue processing according to web.config customErrors (making our custom error handling ineffective), and error information will also be logged to Windows Event Log (which is unnecessary since we're already using log4net).