规则例外,第 1 部分

 

罗布·霍华德
Microsoft Corporation

2001 年 7 月 23 日

让我们面对现实,当我们编写 Web 应用程序时,我们 偶尔 会 (或在我们的政治上更正确的世界中出现 bug,问题) 在我们的代码中。 遗憾的是,似乎测试人员(CEO、CIO、董事会成员、VC 等)越高级,这些问题往往越频繁或更严重。

如果你在 ASP 中进行了任何开发,你会回忆起一条非常有用的 ASP 错误消息,如下所示:

HTTP 500.100 - Internal Server Error - ASP error
Error Type: Microsoft VBScript runtime (0x800A01A8)

作为开发人员,看到此错误消息的第一反应通常是“嗯?”接下来,将转换错误-HTTP 500 内部服务器错误,指示 ASP 代码存在问题。 下一部分是错误类型,在本例中是0x800A01AB的 HRESULT 代码,如果你手上有足够的时间 ,则可以将 MSDN (或使用 Captain Crunch COM HRESULT 机密解码器环) ,并找出代码尝试对不存在的方法进行后期绑定调用。

遗憾的是,对于我们而言,高级测试人员发现这些问题更为常见。 而且,这些高级测试人员通常遵循一个不那么建设性的路线,例如拿起电话,对某人大喊大叫,通常是你的老板。 常见问题是,“如果它导致错误,为什么要使用 Microsoft ASP? 真的,它说它就在那里'ASP 错误'。

ASP.NET 使我们能够以更加结构化和用户友好的方式轻松处理这些类型的错误和其他运行时问题。 我们的应用程序可以向开发人员提供丰富的特定于开发人员的错误消息,我们的高级测试人员可以收到美观且含糊不清的消息,让他们对系统的复杂性感到满意。

此外,你永远不会看到 ASP.NET 错误页 (,除非你自己写) 显示 ASP.NET error。 我们想让你诚实,所以我们说 Application error

ASP.NET 异常处理

ASP.NET 允许我们按照 CLS) 的公共语言规范 (生成任何语言的 Web 应用程序。 遵循 CLS(提交到 ECMA 进行标准化的规范)的语言能够在公共语言运行时 (CLR) 上运行。 CLR 提供垃圾回收、安全代码执行和结构化异常处理等功能。

我们可以在 ASP.NET 应用程序中利用这种独立于语言的结构化异常处理。 结构化异常处理是通过 try/catch/finally 块完成的,并强制我们在异常发生时处理异常。 如果引发异常且未显式处理异常,则会发生常规 ASP.NET 异常,强制应用程序终止而不允许代码继续执行,从而导致错误页。 这使得查找错误变得更加容易。

这与 ASP 代码大不相同。 使用 ASP 代码,我们可以调用 Visual Basic 6 COM 对象的 方法,如果方法中发生错误,则返回错误代码 (HRESULT) 。 但是,我们负责检查错误,通常按如下所示包装代码 (伪代码) :

<%
On Error Resume Next
...
dataObject.SomeBadMethod()
If Error.Number <> 0 Then
  Response.Write("An error occurred in the call to SomeBadMethod()")
  Response.End
End If
dataObject.SomeGoodMethod()
%>

如果未检查上述 ASP 伪代码中的 Error.Number,则代码将在调用 SomeBadMethod () 后继续执行,并直接调用 SomeGoodMethod ()

ASP.NET 中仍然存在检查错误的概念,但必须在错误发生时处理错误:

<Script runat=server>
Public Sub Page_Load(sender As Object, e As EventArgs)
  ...
  Begin Try
    dataObject.SomeBadMethod()
  Catch
    ' Looks like an exception occurred, do work to either
    ' handle the error and clear the exception or fail
  End Try
  ...
End Sub
</Script>

主要区别在于,我们现在仅使用 Try/Catch/Finally 处理异常。 这是一件好事。 发生错误时,我们获取异常的实例或可能派生的、更专用的实例,例如 NoNullAllowedException ,尝试将 null 值插入不允许 null 值的 SQL 表行时。

异常为我们提供了有关所发生事件的详细信息;例如堆栈跟踪、内部异常详细信息、消息和其他详细信息。 这比 COM HRESULT 错误代码好得多!

未经处理的异常

前面我们提到,ASP.NET(或者更确切地说是 CLR)会强制我们在发生错误时处理异常。 我们显然不会在所有代码周围编写 Try/Catch/Finally 块,在未编写的情况下,ASP.NET 仍然为我们提供了一些通过两个事件处理异常的功能:

  • Page_Error
  • Application_Error

页面和应用程序错误事件处理程序

存在异常意外且不发生在 Try/Catch/Finally 块边界内的情况。 这些异常通常是应用程序出现严重错误的指示器。 也就是说,发生了一些异常错误,并且没有正常方法来摆脱错误。 在这些情况下,我们不会使用 Try/Catch/Finally 块包装错误代码,我们仍可以选择在页面或应用程序级别处理错误。

如果选择在页面级别处理错误,则必须提供 Page_Error 事件的实现:

VB.NET

Public Sub Page_Error(sender As Object, e As EventArgs)
   ' Implementation here
End Sub

C#

public void Page_Error(Object sender, EventArgs e) {
   // Implementation here
}

此事件在可能发生错误的 Page 中实现。

或者,我们还可以实现 Application_Error 事件。 Page_Error与 事件不同,Application_Error事件是在 global.asax 中实现的,如果) 实现,则应用程序中发生的任何未经处理的异常都引发此事件 (:

VB.NET

Public Sub Application_Error(sender As Object, e As EventArgs)
   ' Implementation here
End Sub

C#

public void Application_Error(Object sender, EventArgs e) {
   // Implementation here
}

在这两个事件中,我们可以运行代码,例如向管理员发送电子邮件或写入事件日志,指出发生了错误。 在下一列中,我们将讨论写入 Windows 事件日志。

除了运行代码来提醒必要的人员注意应用程序中的异常外,我们仍有机会消除异常(如有必要)。 我们有权访问通过返回 Exception 类的 Server.GetLastError () 方法发生的异常,并且可以使用 API Server.ClearError () 清除异常。

总结

借助公共语言运行时,ASP.NET 开发人员现在可以使用 Try/Catch/Finally 块编写结构化错误处理代码。 CLR 强制我们在错误发生时处理错误,这与 ASP/COM 不同,在 ASP/COM 中,错误可能未选中并可能导致以后混淆。 在下一列中,我们将继续讨论 ASP.NET 错误处理,并查看 ASP.NET 生成的自定义错误页。 我们还将讨论如何实现可将异常详细信息写入 Windows 事件日志的代码。

社区最新动态

用户组: 我最近在圣路易斯的一个伟大的 .NET 用户组中发表了演讲。 8 月 9 ,我会在达拉斯在另一个用户的组发表演讲。 有关详细信息,请参阅 http://www.dnug.net/ViewGroup.aspx?id=21 。 然后在 8 月 28 ,我会在圣地亚哥的用户组发言, (稍后) 发布 URL。 如果你尚未加入 .NET 用户的组,并且你对学习 .NET 很认真,我绝对建议这样做。

会议: Microsoft ASP.NET Connections 会议于 9 月 18日至 21 在佛罗里达州奥兰多举行,会议将是一场以 ASP.NET 为重点的盛会。 有关详细信息,请参阅 http://www.asp-connections.com

ASP.NET 杂志: 在过去的六个月里,ASP.NET 团队一直与 Informant Communications Group 密切合作,为 ASP.NET 开发人员编写了一本杂志。 该杂志将被称为 asp.netPRO,将于今年秋季晚些时候推出。 ASP.NET 团队将积极参与该杂志。 我们将有一个 “询问 ASP.NET 团队 ”栏目和 ASP.NET 团队的许多其他贡献,以及我们许多才华横溢的第三方 ASP.NET 专家。 有关更多详细信息以及注册免费问题,请参阅 http://www.aspnetpro.com

 

Rob Howard 是.NET Framework团队 ASP.NET 项目经理。 他花任何业余时间,要么和家人在一起,要么在华盛顿东部钓鱼。