오류 처리기의 전체 예제

Visual Studio 2010

업데이트: 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 파일을 수정해야 합니다. 구성 파일의 우선 순위가 더 높습니다. 따라서 customErrorsOff로 설정하거나 defaultRedirect 설정을 제거해야 합니다. Web.config 구성 파일의 customErrorsOff로 설정된 경우 Global.asax의 Application_Error 이벤트 처리기에서 처리되지 않은 모든 오류를 처리합니다.

Bb397417.alert_security(ko-kr,VS.100).gif보안 정보:

Global.asax 파일에 Application_Error 처리기가 없는 경우에는 Web.config 파일에서 customErrorsOff로 설정하지 않도록 주의해야 합니다. 사이트에서 오류를 일으킨 임의의 사용자에게 웹 사이트에 대한 손상된 정보가 노출될 수 있습니다.

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 runat="server">
    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 runat="server">
    <title>Exception Handler Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <h2>Default Page</h2>
        <p>
            Click this button to create a InvalidOperationException.<br />
            <asp:Button ID="Submit1" runat="server" CommandArgument="1" 
                OnClick="Submit_Click" Text="Click 1" />
        </p>
        <p>
            Click this button to create a ArgumentOutOfRangeException.<br />
            <asp:Button ID="Submit2" runat="server" CommandArgument="2" 
                OnClick="Submit_Click" Text="Click 2" />
        </p>
        <p>
            Click this button to create a generic Exception.<br />
            <asp:Button ID="Submit3" runat="server" 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 runat="server">
    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 runat="server">
    <title>Generic Error Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <h2>Generic Error Page</h2>
    <asp:Panel ID="InnerErrorPanel" runat="server" Visible="false">
        <p>
            Inner Error Message:<br />
            <asp:Label ID="innerMessage" runat="server" 
                Font-Bold="true" Font-Size="Large" /><br />
        </p>
        <pre>
<asp:Label ID="innerTrace" runat="server" />
        </pre>
    </asp:Panel>
    <p>
        Error Message:<br />
        <asp:Label ID="exMessage" runat="server" 
            Font-Bold="true" Font-Size="Large" />
    </p>
    <pre>
<asp:Label ID="exTrace" runat="server" visible="false" />
    </pre>

    </div>
    </form>
</body>
</html>


HttpErrorPage.aspx

다음 예제에서는 HttpErrorPage.aspx 페이지를 제공합니다. 이 페이지에서도 오류 코드의 값에 따라 원격 사용자에게 표시되는 안전 확인 메시지를 만듭니다. 로컬 사용자에게는 자세한 예외 보고서가 표시됩니다.

<%@ Page Language="C#" %>

<script runat="server">
    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 runat="server">
    <title>Generic Error Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <h2>Http Error Page</h2>    
    <asp:Panel ID="InnerErrorPanel" runat="server" Visible="false">
        <asp:Label ID="innerMessage" runat="server" 
            Font-Bold="true" Font-Size="Large" /><br />
        <pre>
<asp:Label ID="innerTrace" runat="server" />
        </pre>
    </asp:Panel>
    Error Message:<br />
    <asp:Label ID="exMessage" runat="server" 
        Font-Bold="true" Font-Size="Large" />
    <pre>
<asp:Label ID="exTrace" runat="server" visible="false" />
    </pre>

    </div>
    </form>
</body>
</html>


표시: