2009-07-14 1 views
5

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

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

+0

Для записи страницы, которые переадресовывают ошибки, действительно раздражают, так как им очень сложно отправить вам URL-адрес, по которому я увидел ошибку, или повторить попытку позже. –

+0

Кроме того, Server.Transfer не будет работать для частичных обратных обращений к страницам - мы это делали, но он не срабатывал, когда была инициирована ошибка из UpdatePanel. – cloying

ответ

7

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

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

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

+0

+1 Хороший ответ - мне нравится идея дать пользователю немного места для отправки электронной почты. Мы не можем этого сделать из-за размера нашей пользовательской базы, но мы записываем все в db. –

+0

Спасибо, это хорошо сработало для нас. На нашем крупнейшем сайте у нас было 50 000 пользователей, заполнивших нашу онлайн-заявку на 15-20 страниц. И то, что я нашел об этом методе, состоит в том, что он создает чувство неотложности из-за ожиданий пользователя и моих собственных. У меня есть способ побудить меня устранить все ошибки. И как только я это делаю, я трачу гораздо меньше времени на поддержку веб-сайта и больше времени на его улучшение. –

+0

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

1

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

Посмотрите на этот вопрос:

ASP.NET custom error page server GetLastError is null

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

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

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

+1

+1 - Я согласен с тем, что вы не должны показывать ошибку для пользователь. Мы регистрируем его в базе данных, как я опишу в своем ответе. –

1

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

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

+0

+1 От меня - мой ответ немного другой, но мы также используем запись в БД, поэтому я поддержал вас. –

1

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

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

0
Server.ClearError(); 

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

+0

Я считаю, что это предотвратит регистрацию ошибки в журнале событий Windows по умолчанию. – Sam

0

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

В пользовательской ошибки page "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 [ «»] код, но я предпочел переменная сеанса.

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

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

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

Смежные вопросы