Страница пользовательской ошибки ASP.NET для веб-приложения, использующая главную страницу

Справка KB306355: Как создать персонализированные страницы отчетов об ошибках в ASP.NET с помощью Visual С#.NET

Я понимаю, как создать страницу пользовательских ошибок. Существует много примеров того, как это сделать, например, в ссылке выше.

Ни один из примеров, которые я нашел, показывает, как делать то, что я делаю после.

У меня есть веб-приложение, которое использует главную страницу.

На моей главной странице у меня есть элемент управления Label для ошибок, которые будут отображаться на всех страницах:

<h4 id="bannerError"><asp:Label ID="lblError" runat="server" /></h4>

В коде на этой главной странице у меня есть следующее:

public void Page_Error(object sender, EventArgs e) {
  var err = Server.GetLastError().GetBaseException();
  ErrorMessage = String.Format("URL {0}: {1} Error: {2}", Request.Url, err.GetType(), err.Message);
  Server.ClearError();
}

public string ErrorMessage {
  get { return lblError.Text; }
  set {
    LogError(value);
    lblError.Text = value;
  }
}

ErrorMessage - свойство. Мои другие страницы могут легко получить к нему доступ, и я легко мог отредактировать часть о записи ошибки в нашу базу данных сервера.

Конфигурация страницы Web.config (фрагмент):

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <customErrors defaultRedirect="Default.aspx" mode="On">
      <error statusCode="403" redirect="Default.aspx" />
      <error statusCode="404" redirect="Default.aspx" />
    </customErrors>
  </system.web>
</configuration>

Как мне отредактировать мои файлы, чтобы любые ошибки, возникающие на любой из моих страниц в моем приложении (которые были получены на главной странице), просто отображали эту основную информацию через главную страницу, а не перенаправляли страницу на другой URL?

Ответ 1

Вы не сможете использовать элементы управления для установки сообщения об ошибке для необработанных ошибок уровня страницы, поскольку никакие элементы управления не будут созданы (см. статья MS). Вы могли поймать ошибки на уровне страницы и установить содержимое главной страницы следующим образом:

    protected override void OnError(EventArgs e) {
        var err = Server.GetLastError().GetBaseException();
        var errorMessage = String.Format("URL {0}: {1} Error: {2}", Request.Url, err.GetType(), err.Message);
        ((MyMasterPageClass)Master).ShowError(errorMessage);
        Server.ClearError();            
    }

И затем на главной странице задайте контент напрямую:

    public void ShowError(string message) {
        Response.Write(string.Format("<h4 id=\"bannerError\">{0}</h4>", message));
    }

Но опять же, ваша главная страница не будет рендеринга в любом случае, поэтому это своего рода поражение цели. Если вы действительно хотите избежать перенаправления на страницу с ошибкой, вы можете загрузить контент с помощью ajax, используя что-то вроде jQuery.get(), а затем отобразить результаты/ошибки по мере необходимости:

var request = $.get("www.mywebsite.com/Bugs2012.aspx");

request.done(function (data) {
    $("#childContent").html(data);
});

request.fail(function (xhr, status, msg) {
    var displayMsg = "Request could not be completed. ";
    if (status === "error") {
        switch (xhr.status) {
            case 404: 
                displayMsg += "The content could not be found.";
                break;
        }
    }
    $("#bannerError").text(displayMsg);
});

Я попытался создать jsfiddle, но он немного надуман из-за проблем с ajax в междоменном пространстве: js fiddle

Ответ 2

Я знаю, что вопрос заключался в том, как заставить решение MasterPage работать, но я думаю, что использование события уровня Error на уровне приложения - лучший способ заставить обработчик ошибок catch-all пересылать на страницу с ошибкой.

В basckly необходимо обрабатывать Application_Error в файле Global.asax. Здесь вы можете не только обрабатывать все ошибки на уровне страницы, но также ошибки на уровне приложений и ошибки HTTP некоторых типов (если они могут достичь конвейера вашего приложения).

Я думаю, что это лучший и более центированный метод. Также возможно добавление обработчиков событий уровня MasterPage или BasePage, но в качестве второго слоя.

Посмотрите здесь для хорошего примера этого.