Пример обработчиков ошибок

Visual Studio 2010

Обновлен: Ноябрь 2007

В данном примере демонстрируются элементы для обработки исключений на уровне страницы и на уровне приложения.

В данном примере кода представлены следующие файлы:

  • Файл 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 to Off, либо удалить параметр defaultRedirect. Если файл конфигурации Web.config содержит свойство customErrors, которому присвоено значение Off, обработчик событий Application_Error в файле Global.asax будет обрабатывать необработанные ошибки.

Bb397417.alert_security(ru-ru,VS.100).gifПримечание о безопасности.

Нельзя присваивать свойству customErrors в файле Web.config значение Off, если в файле Global.asax не содержится обработчик Application_Error. В этом случае конфиденциальная информация о веб-узле потенциально может быть открытой для всех, что может стать причиной возникновения ошибок на узле.

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 содержит два статических метода: протоколирование исключений в журнале и уведомление системного администратора. Реализация данных методов в коде зависит от потребностей предприятия. Для данного примера необходимо предоставить учетной записи NETWORK SERVICE разрешение на запись в папку App_Data, чтобы включить для приложения функцию записи в журнал ошибок.

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>


Показ: