In my recent post ASP.NET Exception Handling links I wondered why in the article Rich Custom Error Handling with ASP.NET Session is not considered to pass Exception details between global.asax: Application_Error and Rich Custom Error Pages with Redirect method.
The article compare different state possibilities : Application, Context, Cookies, and QueryString.
The application that I am working with used Cache(which technically works as the same way as Application) with SessionID as a key and Response.Redirect() to open a custom error page. The problem with Cache( and with Application) state is that it doesn't work in a web farm environment, because Exception obeject saved on one farm server is not available after Redirect on another farm server(unless farm support session affinity). So if you have 4 web farm servers, only one of 4 errors are shown in the custom error page(which is not good). And the problem is not noticable on development machines(which is very bad).
OK, but if SessionID was used as a key in both Application_Error and custom error page, why not to use Session to pass Exception details. It didn't work for me initially. Post Don't redirect after setting a Session variable (or do it right) describes that it is required to use Response.Redirect overload with endResponse =false. However even after this I wasn't able to retrieve in custom error page object, that was saved to Session in Application_Error .
The problem is that after Application_Error function finished, ASP.NET still considered Exception as not handled, and handles it by logging "Unhandled Exception" to the Application Event Log and interrupting normal event life cycle, which prevents to save the latest Session state changes.
The fix is simple: if you handle Exception in Application_Error , don't forget to call Server.ClearError();
By the way, this is important difference between catch block and Application_Error handler.
In catch block If you do NOT want to "swallow" exception , you should explicitely specify throw.
In Application_Error , if you want to "swallow" exception, you need to call Server.ClearError();
To summarize below is the code, that I am using to pass Exception info from Application_Error to custom error page using Session(actually it is the almost the same code as posted by kurtsune in comments on Bertrand Le Roy's post .
void Application_Error(object sender, EventArgs e)
Exception ex = Server.GetLastError();
HttpContext.Current.Session["Error"] = ex.Message;