Лучший способ передать последнюю ошибку в пользовательский редирект ошибок? - PullRequest
5 голосов
/ 14 июля 2009

Вам было интересно, что вы думаете об этом решении, если это правильный способ передать сообщение об ошибке на пользовательскую страницу?

В web.config:

    <customErrors mode="On" defaultRedirect="~/Error.aspx"></customErrors>

В Global.asax:

<script RunAt="server">
    void Application_Error(object sender, EventArgs e)
    {
    Exception ex = Server.GetLastError();
    if (ex != null && Session != null)
    {
        ex.Data.Add("ErrorTime", DateTime.Now);
        ex.Data.Add("ErrorSession", Session.SessionID);
        HttpContext.Current.Cache["LastError"] = ex;
    }
    }

</script>

В моем Error.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) return;

    if (HttpContext.Current.Cache["LastError"] != null)
    {
        Exception ex = (Exception)HttpContext.Current.Cache["LastError"];
        if (ex.Data["ErrorTime"] != null && ex.Data["ErrorSession"] != null)
            if ((DateTime)ex.Data["ErrorTime"] > DateTime.Now.AddSeconds(-30d) && ex.Data["ErrorSession"].ToString() == Session.SessionID)
                Label1.Text = ex.InnerException.Message;
    }
}

Вопрос: я не хочу делать Server.Transfer из Global.asax, потому что .. я не знаю. Мне показалось неуклюжим. Хотите иметь возможность изменить customErrors на RemoteOnly. Поэтому нужно где-то сохранить последнее исключение, но это не может быть Session, поэтому сохраните его в Cache, но с некоторыми дополнительными данными (time и SessionID), поскольку Cache является глобальным и хочет убедиться, что кто-то не показывает неправильную ошибку.


Я немного изменил свой код. Теперь это просто:

void Application_Error(object sender, EventArgs e)
{
    HttpContext.Current.Cache["LastError"] = Server.GetLastError().GetBaseException();
    Server.ClearError();
}

... и ...

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) return;

    if (HttpContext.Current.Cache["LastError"] != null)
    {
        Exception ex = (Exception)HttpContext.Current.Cache["LastError"];
        if (ex != null)
            Label1.Text = ex.Message;
    }
}

Примечание. SessionID отсутствует, если это анонимный пользователь, и ex.Data. Добавление уже существующего ключа приведет к ошибке, из-за которой я понимаю, что важно вызвать ClearError

Ответы [ 6 ]

7 голосов
/ 15 июля 2009

Я думаю, что это достойный способ сделать это. Я делаю это не так, но мой код слишком длинный для публикации (и в VB.NET).

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

Вдобавок к этим линиям вы также можете собрать данные формы, данные сеанса и все остальное, что имеет значение, и включить их в отчет об ошибках. Это может упростить диагностику проблем.

1 голос
/ 15 июля 2009

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

В нашем случае мы также передаем идентификатор пользователя (если имеется) и страницу, на которой произошла ошибка (Request.URL по-прежнему исправен, когда вы попадаете в глобальную ошибку Application_Error). Таким образом, мы можем отследить ошибку немного проще. Также обратите внимание, что вам не нужно использовать Global.asax с тегом скрипта. Если вы создаете файл Global.asax.cs в своем каталоге App_Code, вы можете просто напрямую кодировать свой C # (хотя это может зависеть от типа проекта).

1 голос
/ 14 июля 2009

Мы делаем то, что может или не может работать для вас. Мы делаем обширную регистрацию в БД. Когда мы получаем ошибку, мы регистрируем ее, и это выдает идентификатор ошибки. Мы перенаправляем на общую страницу с идентификатором ошибки и получаем подробную информацию там.

конечно, это не сработает, когда ошибка «не может подключиться к БД», но это происходит не так часто;)

1 голос
/ 14 июля 2009

Поскольку кеш глобален, это не рекомендуется, так как вы сказали, что можете показывать кому-то неверную ошибку. Я также должен сказать, что вы не должны выводить сообщение об ошибке напрямую конечным пользователям из соображений безопасности.

Посмотрите на эту проблему:

Сервер страниц пользовательских ошибок ASP.NET GetLastError имеет значение null

Чтобы подвести итог, напишите что-то вроде следующего:

Server.Transfer(String.Concat("~/Error.aspx?message=", HttpUtility.UrlEncode(ex.InnerException.Message)))

Вместо того, чтобы полагаться на ASP.NET для перенаправления с использованием настроек в разделе CustomErrors.

0 голосов
/ 03 октября 2013

Я отвечал за создание пользовательской страницы ошибок. Все было довольно просто: в файле web.config у меня было:

<customErrors mode="On">
<error statusCode="404" redirect="~/error-pages/page-not-found.aspx?error=1"
</customErrors>

и в Global.asax в методе Application_Error: какой-то код ...

Server.Transfer("~/error-pages/error.aspx");

На пользовательской странице ошибки "error.aspx": Server.ClearError();

Я не знаю точно, что было изменено, но это больше не работало. Когда код достиг метода Server.Transfer, всегда возникало исключение: ошибка при выполнении дочернего запроса для страницы ...

Я посмотрел на некоторые решения и наконец нашел это. Я изменил свой код, и теперь он, кажется, работает:

<customErrors mode="On" defaultRedirect="~/error-pages/error.aspx">
  <error statusCode="404" redirect="~/error-pages/page-not-found.aspx?error=1" />
</customErrors>

и в методе global.asax:

Session["LastError"] = Server.GetLastError();

Он также работал с кодом Cache [""], но я предпочел переменную Session.

Итак, спасибо за ответы.

  • не забудьте очистить ошибку на пользовательской странице ошибки. Это важно. Кроме того, было бы указано, чтобы не показывать точно всю ошибку пользователю. Возможно в определенном удобном для пользователя формате. И предоставьте всю информацию в лог-файл или отправьте ее по электронной почте или как-нибудь еще.

Надеюсь, это было полезно.

0 голосов
/ 29 октября 2009
Server.ClearError();

Эта строка должна быть помещена в Error.aspx.cs после отображения ErrorMessage, я думаю.

...