页面错误的处理
ASP.NET提供了两级全局异常拦截点,分别位于页面级与应用程序级。
基类Page暴露了一个Error事件,我们可在页面中重写它,捕获页面执行期间引发的未处理异常。
HttpApplication类中也有Error事件,用于捕获整个应用程序中抛出的所有未处理异常。
页面级错误处理
为捕获特定页面的未处理异常,我们需要定义Error事件的处理程序,如下所示:
protected void Page_Error(object sender, EventArgs e)
{
Exception ex = server.GetLastError();
if(ex is NotImplementedException)
Server.Transfer("/errorpages/notimplementexception.aspx");
else
Server.Transfer("/errorpages/apperror.aspx");
Server.ClearError();
}
通过Server对象的GetLastError方法,我们能获取被引发的异常。如果通过Server.Transfer来传输控件,异常信息会被保留,错误页面可调用GetLastError,并显示更详细的信息。最后,一旦所有异常处理执行完毕,应调用ClearError清除错误。
在显示错误消息时,注意不要公开敏感信息以防止恶意用户利用它们对系统发起攻击。我们可以使页面更灵活些,让它判断用户是否位于本地,是否选用自定义标头,并显示有助于错误诊断的详细信息:
if(Request.UserHostAddress == "127.0.0.1")
{
......
}
全局错误处理
添加global.asax文件到程序中,并在预定义的Application_Error方法中编写代码:
void Application_Error(object sender, EventArgs e)
{
......
}
错误与页面映射
当未处理异常抵达调用堆栈的末端时,ASP.NET会生成一个默认页面,显示一个黄屏。通过应用程序web.config文件中的<customErrors>区段,开发者可以对ASP.NET这个功能充分进行定制:
<configuration>
<system.web>
......
<customErrors mode="RemoteOnly" defaultRedirect="/GerericError.aspx" />
</system.web>
</configuration>
不论错误是什么,ASP.NET都会将用户重定向到GenericError.aspx页面。
除将用户重定向到通用的错误页面上,ASP.NET还使我们能够针对发生的不同HTTP错误显示相应的自定义页面,如下示例:
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="/GenericError.aspx">
<error statusCode="404" redirect="/ErrorPages/Error404.aspx" />
<error statusCode="500" redirect="/ErrorPages/Error500.aspx" />
</customErrors>
</system.web>
</configuration>
当底层ASP.NET调用错误页面时,引起错误的页面的URL会被传入其中,示例:
public partial class Error404 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
object o = Request.QueryString["AspxErrorPath"];
if(o != null)
{
......
}
}
}
如果应用程序级错误处理程序、页面级处理程序和各种重定向同时存在,会优先考虑哪一种?应用程序级处理程序优先于其他处理程序。页面级代码会在所有代码处理完HTTP 500内部错误后运行。
ASP.NET跟踪
.NET带有功能丰富的程序跟踪工具集。尤其是Systems.Diagnostics命名空间中定义的Trace和Debug类。这两个类基本相同,都建立在“监听程序”模块基础上。监听程序作为一种驱动程序,会收集跟踪的消息,并将这些消息存储在特定的介质中。
页面跟踪的启用方法
我们可在应用程序的web.config文件中切换trace属性的开关状态:
<configuration>
<system.web>
<trace enabled="true" pageOutput="true" />
</system.web>
</configuration>
pageOutput属性用于提示是否将输出显示在页面中。如果pageOutput被设置为false,跟踪输出会被自动发送到ASP.NET的跟踪工具(trace.axd)中。
@Page指令中的trace属性默认为false,如果为true,跟踪信息就会被显示在页面的底部。
@Page指令还提供了TraceMode属性,使我们能够选择被显示数据的排序方式。可能的值为SotrByCategory和SortByTime,默认值为SortByTIme。
Page类提供了两个属性TraceModeValue和TraceEnabled分别对应与上述的@Page指令属性。
Page类与跟踪有关的第三个属性是Trace,它返回TraceContext类的实例。通过TraceContext类的方法,可向ASP.NET页面中追加跟踪日志。在HTTP请求建立时,便会创建该类的实例。跟踪对象通过HttpContext类的Trace属性暴露出来。
TraceContext类的IsEnabled属性表示跟踪是否开启,TraceMode属性表示跟踪记录在页面中的排列模式。
TraceContext类的Write和Warn方法输出消息,这两个方法基本相同,唯一差别在于Warn输出消息为红色。
使用Write方法与Warn方法传送的文本都会显示在HTML页面中,但并未对HTML格式标签进行任何处理。该文本是以纯文本的形式写入的。如果要获得加粗字符,直接对跟踪消息的子字符串添加<b>和</b>即可。
如果外部类要向当前HTTP请求的跟踪日志中发送文本,则可这样表达:
System.Web.HttpContext.Current.Trace.Write(category, msg);
一旦应用程序跟踪功能被启用,每个页面请求都会将特定页面的跟踪信息转给查看器。我们可在应用程序根目录下请求trace.axd打开跟踪查看器(如:http://localhost:1105/Core35/Trace.axd)。
跟踪查看器能够缓存的请求数由requestLimit属性限定(默认值为10)。示例:
<system.web>
<trace enable="true" requestList="20" />
</system.web>
跟踪查看器会自动跟踪所有请求,并缓存每个请求的完整跟踪信息。当请求数达到上限后,其他请求便不会被缓存,除非当前的跟踪信息被手动删除。