ASP.NET 自定义错误






4.36/5 (27投票s)
2002年5月28日
6分钟阅读

446663
在本文中,我将讨论自定义默认错误页面、操作配置文件以及在发生错误时向管理员发送通知。
引言
结构化异常处理是 CLR 的基本组成部分,为 .NET 程序员提供了一种管理错误的好方法。除了 CLR 异常系统之外,ASP.NET 还提供了处理错误的方法。
当应用程序中发生运行时或设计时错误时,ASP.NET 会显示一个默认的错误页面,该页面简要描述了错误以及发生错误的行号。开发人员在测试应用程序时会希望看到这个默认的错误页面,因为描述有助于他纠正错误。但是,他绝不希望用户尝试访问他的应用程序时看到这个错误页面。用户对错误信息最不关心。与其显示默认错误页面,不如显示一个自定义的错误页面,让用户能够将错误通知发送给管理员。
解释
考虑一个 ASP.NET 应用程序的示例,该应用程序有意生成错误以显示 ASP.NET 如何检测错误并显示默认错误页面。下面给出的 WebForm 包含一个标签和一个按钮服务器控件。在按钮单击事件的事件处理程序中,用户将被重定向到另一个 WebForm Trial.aspx。由于正在重定向的页面丢失,ASP.NET 将显示默认错误页面,指示这是一个运行时错误。
与经典 ASP 不同,ASP.NET 将业务逻辑的代码与内容(即 HTML 和界面逻辑)分开。示例应用程序有两个文件,名为 webform1.aspx 包含内容,webform1.aspx.vb 包含代码。
WebForm1.aspx
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="webform1.aspx.vb"
Inherits="ErrorSample.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title></title>
<meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
<meta name="CODE_LANGUAGE" content="Visual Basic 7.0">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Label id="Message" style="Z-INDEX: 101; LEFT: 34px;
POSITION: absolute; TOP: 46px" runat="server"></asp:Label>
<asp:Button id="ErrorButton" style="Z-INDEX: 102; LEFT: 268px;
POSITION: absolute; TOP: 41px" runat="server"
Text="Generate Error"></asp:Button>
</form>
</body>
</HTML>
WebForm1.aspx.vb
Public Class WebForm1
Inherits System.Web.UI.Page
Protected WithEvents Message As System.Web.UI.WebControls.Label
Protected WithEvents ErrorButton As System.Web.UI.WebControls.Button
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)_
Handles MyBase.Load
Message.Text = "This sample page generates an Error..."
End Sub
Public Sub ErrorButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)_
Handles ErrorButton.Click
Response.Redirect("Trial.aspx")
End Sub
End Class
现在,如果您尝试在浏览器中查看上面的 WebForm,您将看到下面显示的网页

现在,如果您单击标记为“Generate Error”的按钮,您将看到下面显示的默认 ASP.NET 错误页面。

自定义错误页面
要自定义默认错误页面,需要更改应用程序的默认配置设置。
ASP.NET 应用程序可以工作在三种错误模式下
1) 关闭模式
2) 开启模式
3) 仅远程模式
Error 模式属性决定是否显示 ASP.NET 错误消息。默认情况下,模式值为“RemoteOnly”。
关闭模式
当 error 属性设置为“Off”时,在发生错误的情况下,ASP.NET 会为本地用户和远程用户使用其默认错误页面。
开启模式
在“On”模式下,ASP.NET 会为本地用户和远程用户使用用户定义的自定义错误页面,而不是其默认错误页面。如果未指定自定义错误页面,ASP.NET 将显示描述如何启用远程查看错误的错误页面。
仅远程
ASP.NET 错误页面仅显示给本地用户。远程请求将首先检查自定义错误页面的配置设置,或者最终显示 IIS 错误。
配置文件
可以通过在配置文件 web.config 的 <customErrors>
标签中为 defaultRedirect
属性添加值来实现错误页面的自定义。此文件确定底层应用程序的配置设置。
关闭模式
在此场景中,将 mode 属性值设置为“Off”,如下所示
Web.Config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<customErrors mode="Off" />
</system.web>
</configuration>
当从远程计算机在浏览器中查看示例 ASP.NET 网页时,将看到下面显示的默认错误页面。

上面的示例 thus 表明,无论是本地访问还是远程访问,都会显示 ASP.NET 错误页面。
开启模式
在此场景中,将 mode 属性值设置为“On”,如下所示
Web.Config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<customErrors defaultRedirect="error.htm" mode="On" />
</system.web>
</configuration>
如配置文件所示,“defaultRedirect”属性已设置为用户定义的页面 error.htm。用户定义的错误页面可以是 ASP.NET Web 页面、经典 ASP 页面或简单的 HTML 页面。
例如,用户定义的错误页面 error.htm 的内容可以如下给出
Error.htm
<HTML>
<BODY>
<b>We are very sorry for the inconvenience caused to you...<br> </b>
</BODY>
</HTML>
当从远程/本地计算机在浏览器中查看示例 ASP.NET 网页时,将看到下面显示的自定义错误页面。

仅远程模式
在此场景中,将 mode 属性值设置为“RemoteOnly”,如下所示
Web.Config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<customErrors defaultRedirect="error.htm" mode="RemoteOnly" />
</system.web>
</configuration>
由于已设置 defaultRedirect 属性,如果从远程计算机请求页面,页面将重定向到 error.htm;如果从本地计算机请求页面,则显示默认错误页面。
向管理员通知错误
在实际的 Web 应用程序中,自定义错误页面不是唯一的要求。如果遇到错误,应将错误报告给管理员,以便进行纠正,从而使后续的请求能够正常工作而不会出现任何错误。
可以通过以下两种方式之一将错误通知发送给管理员
1) 错误可以作为日志条目记录在管理员计算机的 Windows 事件日志中
2) 可以向管理员发送一封包含适当错误消息的电子邮件
写入事件日志
在 ASP.NET 中,可以通过在页面级错误事件中编写适当的代码来以编程方式处理错误,用于单个页面上的错误;或者在应用程序级错误事件中处理应用程序中的任何页面可能发生的错误。
因此,应根据应用程序的要求,在上述任一事件中编写写入事件日志的代码。为了说明这个例子,我将代码写在了应用程序级别的事件中,并将错误模式设置为“RemoteOnly”,将 defaultRedirect
属性设置为 error.htm。应用程序级别的错误事件应包含在同一应用程序文件夹中的全局文件 global.asax 中。
全局文件的内容可以如下给出
写入事件日志中的日志条目
Imports System.Web
Imports System.Web.SessionState
Imports System.Diagnostics
Public Class Global
Inherits System.Web.HttpApplication
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim ErrorDescription As String = Server.GetLastError.ToString
'Creation of event log if it does not exist
Dim EventLogName As String = "ErrorSample"
If (Not EventLog.SourceExists(EventLogName)) Then
EventLog.CreateEventSource(EventLogName, EventLogName)
End If
' Inserting into event log
Dim Log As New EventLog()
Log.Source = EventLogName
Log.WriteEntry(ErrorDescription, EventLogEntryType.Error)
End Sub
End Class
事件日志支持由 .NET 通过 System.Diagnostics
命名空间提供。因此,为了使上述代码正常工作,在项目中添加对上述命名空间的引用非常重要。在应用程序级别的错误事件处理程序中,如果事件日志中不存在名为“ErrorSample”的日志,则会创建一个。如果已存在,则将错误条目添加到现有事件列表中。从远程计算机在浏览器中查看页面后,该事件将列在管理员计算机的事件日志中,如下所示

通过选择相应的事件并双击它,可以查看错误的描述。
如下所示会弹出另一个窗口

向管理员发送电子邮件
为了说明这个例子,我在应用程序级别的错误事件中编写了发送电子邮件给管理员的代码。全局文件的内容可以如下给出
Imports System.Web
Imports System.Web.SessionState
Imports System.Web.Mail
Public Class Global
Inherits System.Web.HttpApplication
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim mail As New MailMessage()
Dim ErrorMessage = "The error description is as follows : " &_
Server.GetLastError.ToString
mail.To = "administrator@domain.com"
mail.Subject = "Error in the Site"
mail.Priority = MailPriority.High
mail.BodyFormat = MailFormat.Text
mail.Body = ErrorMessage
SmtpMail.Send(mail)
End Sub
End Class
在上面的代码中,SMTP 服务被用来发送邮件。SMTP 邮件服务支持由 .NET 通过 System.Web.Mail
命名空间提供。因此,为了使上述代码正常工作,在项目中添加对上述命名空间的引用非常重要。