오류 처리기의 전체 예제
업데이트: 2007년 11월
이 코드 예제에는 페이지 수준 및 응용 프로그램 수준 예외 처리를 위한 요소가 모두 포함되어 있습니다.
코드 예제 파일
이 코드 예제의 파일은 다음과 같습니다.
Web.config
Global.asax
Default.aspx
ExceptionUtility(App_Code 폴더에 배치)
GenericErrorPage.aspx
HttpErrorPage.aspx
Web.config
다음 예제에서는 Web.config 파일을 제공합니다. customErrors는 처리되지 않은 모든 오류를 HttpErrorPage.aspx 파일로 디렉션하도록 초기 설정되어 있습니다.
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" />
<!-- Turn on Custom Errors -->
<customErrors
mode="RemoteOnly"
defaultRedirect="HttpErrorPage.aspx">
</customErrors >
</system.web>
</configuration>
Global.asax
다음 예제에서는 Global.asax 파일을 제공합니다. Global.asax 파일에서 오류 이벤트 처리기를 활성화하려면 Web.config 파일을 수정해야 합니다. 구성 파일의 우선 순위가 더 높습니다. 따라서 customErrors를 Off로 설정하거나 defaultRedirect 설정을 제거해야 합니다. Web.config 구성 파일의 customErrors가 Off로 설정된 경우 Global.asax의 Application_Error 이벤트 처리기에서 처리되지 않은 모든 오류를 처리합니다.
보안 정보: |
---|
Global.asax 파일에 Application_Error 처리기가 없는 경우에는 Web.config 파일에서 customErrors를 Off로 설정하지 않도록 주의해야 합니다. 사이트에서 오류를 일으킨 임의의 사용자에게 웹 사이트에 대한 손상된 정보가 노출될 수 있습니다. |
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
// Give the user some information, but
// stay on the default page
Exception exc = Server.GetLastError();
Response.Write("<h2>Global Page Error</h2>\n");
Response.Write(
"<p>" + exc.Message + "</p>\n");
Response.Write("Return to the <a href='Default.aspx'>" +
"Default Page</a>\n");
// Log the exception and notify system operators
ExceptionUtility.LogException(exc, "DefaultPage");
ExceptionUtility.NotifySystemOps(exc);
// Clear the error from the server
Server.ClearError();
}
ExceptionUtility
다음 예제에서는 ExceptionUtility 파일을 제공합니다. 오류 로그를 컴퓨터의 ErrorLog 파일로 디렉션하거나, 컴퓨터가 웹 팜에 속한 경우 데이터베이스를 비롯한 전역으로 사용 가능한 텍스트 파일에 오류 로그를 기록할 수 있습니다. 문제가 발생하면 해당 사실을 시스템 관리자에게 즉시 알려야 할 수도 있습니다. 다음 ExceptionUtility에는 두 개의 정적 메서드가 있습니다. 그 중 하나는 예외를 기록하고, 다른 하나는 시스템 관리자에게 문제를 알립니다. 이들 메서드를 코드에서 구현하는 방법은 조직의 필요에 따라 달라집니다. 이 예제에서는 App_Data 폴더에 대한 NETWORK SERVICE에 쓰기 권한을 부여하여 응용 프로그램에서 오류 로그를 쓸 수 있게 해야 합니다.
using System;
using System.IO;
using System.Web;
// Create our own utility for exceptions
public sealed class ExceptionUtility
{
// All methods are static, so this can be private
private ExceptionUtility()
{ }
// Log an Exception
public static void LogException(Exception exc, string source)
{
// Include enterprise logic for logging exceptions
// Get the absolute path to the log file
string logFile = "App_Data/ErrorLog.txt";
logFile = HttpContext.Current.Server.MapPath(logFile);
// Open the log file for append and write the log
StreamWriter sw = new StreamWriter(logFile, true);
sw.Write("******************** " + DateTime.Now);
sw.WriteLine(" ********************");
if (exc.InnerException != null)
{
sw.Write("Inner Exception Type: ");
sw.WriteLine(exc.InnerException.GetType().ToString());
sw.Write("Inner Exception: ");
sw.WriteLine(exc.InnerException.Message);
sw.Write("Inner Source: ");
sw.WriteLine(exc.InnerException.Source);
if (exc.InnerException.StackTrace != null)
sw.WriteLine("Inner Stack Trace: ");
sw.WriteLine(exc.InnerException.StackTrace);
}
sw.Write("Exception Type: ");
sw.WriteLine(exc.GetType().ToString());
sw.WriteLine("Exception: " + exc.Message);
sw.WriteLine("Source: " + source);
sw.WriteLine("Stack Trace: ");
if (exc.StackTrace != null)
sw.WriteLine(exc.StackTrace);
sw.WriteLine();
sw.Close();
}
// Notify System Operators about an exception
public static void NotifySystemOps(Exception exc)
{
// Include code for notifying IT system operators
}
}
Default.aspx
다음 예제에서는 Default.aspx 페이지를 제공합니다. 이 파일은 각각 서로 다른 예외를 발생시키는 단추 세 개를 제공합니다. 페이지의 Page_Error 처리기에서는 특정 오류를 필터링하고 이러한 세 가지 예외를 서로 다른 세 가지 방법으로 처리합니다. 여기에서는 페이지를 통해 처리되지 않는 네 번째 종류의 오류인 존재하지 않는 파일에 대한 링크도 제공합니다.
<%@ Page Language="C#" %>
<script >
protected void Submit_Click(object sender, EventArgs e)
{
string arg = ((Button)sender).CommandArgument;
if (arg.Equals("1"))
{
// Exception handled on the Generic Error Page
throw new InvalidOperationException("Invalid click operation?!");
}
else if (arg.Equals("2"))
{
// Exception handled on the current page
throw new ArgumentOutOfRangeException("click?!");
}
else
{
// Exception handled on the Http Error Page (per Web.Config)
throw new Exception("Generic click problem?!");
}
}
private void Page_Error(object sender, EventArgs e)
{
// Get last error from the server
Exception exc = Server.GetLastError();
// Filter for a specific kind of exception
if (exc is ArgumentOutOfRangeException)
{
// Give the user some information, but
// stay on the default page
Response.Write("<h2>Default Page Error</h2>\n");
Response.Write(
"<p>ArgumentOutOfRange: Your click must have " +
"been out of range?!</p>\n");
Response.Write("Return to the <a href='Default.aspx'>" +
"Default Page</a>\n");
// Log the exception and notify system operators
ExceptionUtility.LogException(exc, "DefaultPage");
ExceptionUtility.NotifySystemOps(exc);
// Clear the error from the server
Server.ClearError();
}
// Filter for other kinds of exceptions
else if (exc is InvalidOperationException)
{
// Pass the error on to the Generic Error page
Server.Transfer("GenericErrorPage.aspx", true);
}
else
{
// Pass the error on to the default global handler
}
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
<title>Exception Handler Page</title>
</head>
<body>
<form id="form1" >
<div>
<h2>Default Page</h2>
<p>
Click this button to create a InvalidOperationException.<br />
<asp:Button ID="Submit1" CommandArgument="1"
OnClick="Submit_Click" Text="Click 1" />
</p>
<p>
Click this button to create a ArgumentOutOfRangeException.<br />
<asp:Button ID="Submit2" CommandArgument="2"
OnClick="Submit_Click" Text="Click 2" />
</p>
<p>
Click this button to create a generic Exception.<br />
<asp:Button ID="Submit3" CommandArgument="3"
OnClick="Submit_Click" Text="Click 3" />
</p>
<p>Click this link to attempt to access a non-existent page:<br />
<a href="NoPage.aspx">NoPage.aspx</a>
</p>
</div>
</form>
</body>
</html>
GenericErrorPage.aspx
다음 예제에서는 GenericErrorPage.aspx 페이지를 제공합니다. 이 페이지에서는 원격 사용자에게 표시되는 안전 확인 메시지를 만듭니다. 응용 프로그램 개발자 및 테스터 같은 로컬 사용자에게는 자세한 예외 보고서가 표시됩니다.
<%@ Page Language="C#" %>
<script >
protected Exception ex = null;
protected void Page_Load(object sender, EventArgs e)
{
// Get the last error from the server
Exception ex = Server.GetLastError();
// Create a safe message
string safeMsg = "A problem has occurred in the web site. ";
// Show Inner Exception fields for local access
if (ex.InnerException != null)
{
innerTrace.Text = ex.InnerException.StackTrace;
InnerErrorPanel.Visible = Request.IsLocal;
innerMessage.Text = ex.InnerException.Message;
}
// Show Trace for local access
if (Request.IsLocal)
exTrace.Visible = true;
else
ex = new Exception(safeMsg, ex);
// Fill the page fields
exMessage.Text = ex.Message;
exTrace.Text = ex.StackTrace;
// Log the exception and notify system operators
ExceptionUtility.LogException(ex, "Generic Error Page");
ExceptionUtility.NotifySystemOps(ex);
// Clear the error from the server
Server.ClearError();
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
<title>Generic Error Page</title>
</head>
<body>
<form id="form1" >
<div>
<h2>Generic Error Page</h2>
<asp:Panel ID="InnerErrorPanel" Visible="false">
<p>
Inner Error Message:<br />
<asp:Label ID="innerMessage"
Font-Bold="true" Font-Size="Large" /><br />
</p>
<pre>
<asp:Label ID="innerTrace" />
</pre>
</asp:Panel>
<p>
Error Message:<br />
<asp:Label ID="exMessage"
Font-Bold="true" Font-Size="Large" />
</p>
<pre>
<asp:Label ID="exTrace" visible="false" />
</pre>
</div>
</form>
</body>
</html>
HttpErrorPage.aspx
다음 예제에서는 HttpErrorPage.aspx 페이지를 제공합니다. 이 페이지에서도 오류 코드의 값에 따라 원격 사용자에게 표시되는 안전 확인 메시지를 만듭니다. 로컬 사용자에게는 자세한 예외 보고서가 표시됩니다.
<%@ Page Language="C#" %>
<script >
protected HttpException ex = null;
protected void Page_Load(object sender, EventArgs e)
{
ex = (HttpException)Server.GetLastError();
string safeMsg = String.Empty;
// Filter for Error Codes and set text
if (ex.ErrorCode >= 400 && ex.ErrorCode < 500)
{
ex = new HttpException
(ex.ErrorCode,
"Your file could not be found or " +
"there was an access problem.", ex);
}
else if (ex.ErrorCode > 499)
ex = new HttpException
(ex.ErrorCode,
"There was an error on the server.", ex);
else
ex = new HttpException
(ex.ErrorCode,
"There was a problem " +
"with the web site.", ex);
// Log the exception and notify system operators
ExceptionUtility.LogException(ex, "HttpErrorPage");
ExceptionUtility.NotifySystemOps(ex);
// Fill the page fields
exMessage.Text = ex.Message;
exTrace.Text = ex.StackTrace;
// Show Inner Exception fields for local access
if (ex.InnerException != null)
{
innerTrace.Text = ex.InnerException.StackTrace;
InnerErrorPanel.Visible = Request.IsLocal;
innerMessage.Text = ex.InnerException.Message;
}
// Show Trace for local access
exTrace.Visible = Request.IsLocal;
// Clear the error from the server
Server.ClearError();
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
<title>Generic Error Page</title>
</head>
<body>
<form id="form1" >
<div>
<h2>Http Error Page</h2>
<asp:Panel ID="InnerErrorPanel" Visible="false">
<asp:Label ID="innerMessage"
Font-Bold="true" Font-Size="Large" /><br />
<pre>
<asp:Label ID="innerTrace" />
</pre>
</asp:Panel>
Error Message:<br />
<asp:Label ID="exMessage"
Font-Bold="true" Font-Size="Large" />
<pre>
<asp:Label ID="exTrace" visible="false" />
</pre>
</div>
</form>
</body>
</html>