Лучший способ передать последнюю ошибку в пользовательское перенаправление ошибок?
-
13-09-2019 - |
Вопрос
Интересно, что вы думаете об этом решении, если это правильный способ передать сообщение об ошибке на пользовательскую страницу?
В веб.конфигурации:
<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.
Итак, спасибо за ответы.
- не забудьте удалить ошибку на пользовательской странице ошибок.Это важно.Кроме того, будет указано, что пользователю не следует показывать все ошибки.Возможно, в определенном удобном для пользователя формате.И предоставьте всю информацию в файле журнала, отправьте ее по электронной почте или как-нибудь еще.
Надеюсь, это было полезно.