Лучший способ передать последнюю ошибку в пользовательское перенаправление ошибок?

StackOverflow https://stackoverflow.com/questions/1127236

Вопрос

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

В веб.конфигурации:

    <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.Поэтому нужно где-то сохранить последнее исключение, но это не может быть сеанс, поэтому сохраните его в кеш, но с некоторыми дополнительными данными (время и идентификатор сеанса), поскольку кеш является глобальным и вы хотите убедиться, что кто-то не покажет неправильную ошибку.


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

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.

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

Взгляните на этот вопрос:

Сервер настраиваемой страницы ошибок ASP.NET GetLastError имеет значение null

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

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

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

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

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

Server.ClearError();

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

Я отвечал за создание пользовательской страницы ошибок.Все было довольно просто:в файле 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.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top