I think ASP.Net launches a new response after ApplicationError, just for a different error-handling page. Try tacking into this response.
Update OK: Here's how to do it!
I wanted to make sure we can both attach an error handler and that we can gracefully handle the event in a page, so we can't make the last server error null, and we also want to be able to add headers!
In web.config, add:
<customErrors redirectMode="ResponseRewrite" mode="On">
<error statusCode="500" redirect="~/ErrorHandler.aspx"/>
</customErrors>
Or whatever error specifically you're looking to catch. And under httpModules:
<add name="ErrorModule" type="TestErrorLifecycle.ErrorModule, TestErrorLifecycle"/>
The code to log the error is in this module:
public class ErrorModule : IHttpModule
{
private volatile object locker = new object();
public void Init(HttpApplication context)
{
context.Error += context_Error;
}
void context_Error(object sender, EventArgs e)
{
var app = sender as HttpApplication;
lock (locker)
{
assertLogDirectory(app.Server);
using (var fs = File.AppendText(app.Server.MapPath("~/logs/errorlog.txt")))
{
var lastException = app.Server.GetLastError();
if (lastException == null) throw new ApplicationException("Not expected...");
fs.WriteLine(lastException.Message);
}
}
// we could also do a Request.Redirect() here...
}
private void assertLogDirectory(HttpServerUtility server)
{
var logdir = server.MapPath("~/logs/");
if (!Directory.Exists(logdir))
Directory.CreateDirectory(logdir);
}
public void Dispose()
{
}
}
I just wrote it to the filesystem. You could use kernel file transactions or an exclusive lock or whatever, but because I know I will only write to this file from here, I chose a simple private semaphore.
I added this in Default.aspx.cs just to test:
protected void Page_Load(object sender, EventArgs e)
{
throw new ApplicationException("wtf, something wrong??!");
}
Created file ErrorHandler.aspx with this in it (some parts omitted for shortness):
<body>
<h2>Error handler</h2>
<form id="form1" runat="server">
<p>Last error: <asp:Label ID="lblError" runat="server" /></p>
</form>
</body>
And here's the page-class:
public partial class ErrorHandler : Page
{
public ErrorHandler()
{
Load += ErrorHandler_Load;
}
private void ErrorHandler_Load(object sender, EventArgs e)
{
Response.AddHeader("X-TESTING", "Yes it works...");
lblError.Text = Server.GetLastError() == null ? "noo, why is it null?!?" : Server.GetLastError().Message;
}
}
Finally, I get these response headers at the ErrorHandler.aspx:
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 23 Feb 2009 00:37:45 GMT
X-AspNet-Version: 2.0.50727
X-TESTING: Yes it works...
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 725
Connection: Close
200 OK
If you try to add to Response.Headers-collection directly you need to run IIS in pipeline mode: http://forums.asp.net/p/1253457/2323117.aspx
I hope this helps! Cheers
Henrik
Classic mode (the only mode in IIS6 and below) is a mode where IIS only works with ISAPI extensions and ISAPI filters directly. In fact, in this mode, ASP.NET is just an ISAPI extension (aspnet_isapi.dll) and an ISAPI filter (aspnet_filter.dll). IIS just treats ASP.NET as an external plugin implemented in ISAPI and works with it like a black box (and only when it's needs to give out the request to ASP.NET). In this mode, ASP.NET is not much different from PHP or other technologies for IIS.
Integrated mode, on the other hand, is a new mode in IIS7 where IIS pipeline is tightly integrated (i.e. is just the same) as ASP.NET request pipeline. ASP.NET can see every request it wants to and manipulate things along the way. ASP.NET is no longer treated as an external plugin. It's completely blended and integrated in IIS. In this mode, ASP.NET HttpModule
s basically have nearly as much power as an ISAPI filter would have had and ASP.NET HttpHandler
s can have nearly equivalent capability as an ISAPI extension could have. In this mode, ASP.NET is basically a part of IIS.
Best Answer
HttpContext.Current.ApplicationInstance.CompleteRequest();
Documentation