Monday, November 7

如何在ASP.NET的CustomErrorPage里捕捉UnhandledException

我们知道ASP.NET的web.config里面可以设置CustomErrorPage,就像下面这个样子。

<customErrors mode="On" defaultRedirect="errorpage.aspx" >
<error statusCode="404" redirect="error404.aspx"></error>
</customErrors>

可是你在其他的aspx程序里抛出一个异常,在errorpage.aspx里并不能被捕捉到
in WebForm1.aspx
private void Button1_Click(object sender, System.EventArgs e)
{
throw new Exception("A Error Raised");
}

in errorpage.aspx
private void Page_Load(object sender, System.EventArgs e)
{
Exception ex = Server.GetLastError(); //这里永远返回null
if( ex!=null )
{
Label1.Text+= ex.Message;
}
}

google到一个解决方案:Custom Error Pages in ASP.NET

正像作者mattwag所说在Application_Error 以后会开始一个新的Session,即使Server里曾经存在的LastError也失去了踪影。
WebForm1.aspx抛出的异常最终会被global.asax的Application_Error处理,在这里如果没有Server.ClearError();的话,那么就会跳到在Web.config里指定的CustomErrorPage,但是异常的细节并没有办法直接获得。
mattwag将异常信息保存在session里,然后使用Server.Transfer使得session不被刷新,来达到目的。

这让我想到另一个比较简单的方案就是使用Application来保存异常信息,如下:

in global.asax.cs
protected void Application_Error(Object sender, EventArgs e)
{
Exception ex = Server.GetLastError().InnerException;
Application["UnhandledException"]=ex;
}

in errorpage.aspx
private void Page_Load(object sender, System.EventArgs e)
{
Exception ex = (Exception)Application["UnhandledException"];
Application.Remove("UnhandledException");
if( ex!=null )
{
//Write your code here like
//Label1.Text+= ex.Message;
}
}

适当地配置web.config和书写errorpage.aspx可以达到你需要的效果。
比如使用在子目录下的错误处理页。
<customerrors mode="On" defaultredirect="~/Subfolder/CustomErrorPage.aspx">
</customerrors>

No comments: