ASP.NET пользовательская страница ошибки-сервер.GetLastError () имеет значение null
у меня есть настраиваемая страница ошибок, настроенная для моего приложения:
<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx"
/>
В Глобальном Масштабе.asax, Application_Error (), следующий код работает для получения сведений об исключении:
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.GetBaseException() != null)
ex = ex.GetBaseException();
}
к тому времени, как я доберусь до своей страницы ошибок (~/errors/GeneralError.aspx.КС), сервер.GetLastError () - это null
есть ли способ я могу получить сведения об исключении на странице ошибки, а не в глобальном.асакс.в CS ?
ASP.NET 3.5 на Vista / IIS7
10 ответов:
более пристально глядя на мою паутину.настройка конфигурации, один из комментариев в этот пост очень полезен
в asp.net 3.5 с пакетом обновления 1 появился новый параметр redirectMode
Так что мы можем изменить
customErrors
добавить этот параметр:<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />
the
ResponseRewrite
режим позволяет нам загружать "страницу ошибок" без перенаправления браузера, поэтому URL-адрес остается прежним, и, что важно для меня, информация об исключении не теряется.
ОК, я нашел этот пост: http://msdn.microsoft.com/en-us/library/aa479319.aspx
с этой очень наглядной диаграммой:
диаграмма http://i.msdn.microsoft.com/Aa479319.customerrors_01(Ан-нас,в MSDN.10).гиф
по сути, чтобы получить эти сведения об исключении, мне нужно хранить их самостоятельно в глобальном масштабе.asax, для последующего извлечения на моей странице пользовательских ошибок.
кажется, лучший способ-сделать большую часть работы в Глобальный.asax, с пользовательскими страницами ошибок, обрабатывающими полезное содержимое, а не логику.
сочетание того, что сказал Нейлитдаун и Виктор. Предпочтительный / самый простой способ-использовать ваш глобальный.Asax для хранения ошибки, а затем перенаправить на пользовательскую страницу ошибки.
глобальные.асакс:
void Application_Error(object sender, EventArgs e) { // Code that runs when an unhandled error occurs Exception ex = Server.GetLastError(); Application["TheException"] = ex; //store the error for later Server.ClearError(); //clear the error so we can continue onwards Response.Redirect("~/myErrorPage.aspx"); //direct user to error page }
кроме того, вам нужно настроить свой web.конфигурации:
<system.web> <customErrors mode="RemoteOnly" defaultRedirect="~/myErrorPage.aspx"> </customErrors> </system.web>
и, наконец, сделайте все, что вам нужно, за исключением того, что вы сохранили в своем страница ошибки:
protected void Page_Load(object sender, EventArgs e) { // ... do stuff ... //we caught an exception in our Global.asax, do stuff with it. Exception caughtException = (Exception)Application["TheException"]; //... do stuff ... }
попробуйте использовать что-то вроде
Server.Transfer("~/ErrorPage.aspx");
внутриApplication_Error()
метод глобальной.асакс.csзатем в
Page_Load()
из ErrorPage.aspx.cs вы должны быть в порядке, чтобы сделать что-то вроде:Exception exception = Server.GetLastError().GetBaseException();
Server.Transfer()
кажется, чтобы сохранить исключение висит вокруг.
хотя здесь есть несколько хороших ответов, я должен отметить, что не рекомендуется отображать сообщения об исключениях системы на страницах ошибок (что я предполагаю, что вы хотите сделать). Вы можете непреднамеренно раскрыть то, что вы не хотите делать, злонамеренным пользователям. Например, сообщения об исключениях Sql Server очень подробны и могут давать имя пользователя, пароль и сведения о схеме базы данных при возникновении ошибки. Эта информация не должна отображаться до конца пользователь.
одно важное соображение, которое я думаю, что все здесь отсутствует,-это сценарий балансировки нагрузки (веб-ферма). Так как сервер, который выполняет глобальный.asax может отличаться от сервера, на котором выполняется пользовательская страница ошибки, сохранение объекта исключения в приложении не является надежным.
Я все еще ищу надежное решение этой проблемы в конфигурации веб-фермы и/или хорошее объяснение от MS о том, почему вы просто не можете забрать исключение с помощью Сервер.GetLastError на пользовательской странице ошибки, как вы можете в глобальном.эйсакс application_error для перехвата.
P. S. Это небезопасно для хранения данных в коллекции приложения без блокировки, а затем разблокировки.
вот мое решение..
В Глобальном Масштабе.aspx:
void Application_Error(object sender, EventArgs e) { // Code that runs when an unhandled error occurs //direct user to error page Server.Transfer("~/ErrorPages/Oops.aspx"); }
В Упс.aspx:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) LoadError(Server.GetLastError()); } protected void LoadError(Exception objError) { if (objError != null) { StringBuilder lasterror = new StringBuilder(); if (objError.Message != null) { lasterror.AppendLine("Message:"); lasterror.AppendLine(objError.Message); lasterror.AppendLine(); } if (objError.InnerException != null) { lasterror.AppendLine("InnerException:"); lasterror.AppendLine(objError.InnerException.ToString()); lasterror.AppendLine(); } if (objError.Source != null) { lasterror.AppendLine("Source:"); lasterror.AppendLine(objError.Source); lasterror.AppendLine(); } if (objError.StackTrace != null) { lasterror.AppendLine("StackTrace:"); lasterror.AppendLine(objError.StackTrace); lasterror.AppendLine(); } ViewState.Add("LastError", lasterror.ToString()); } } protected void btnReportError_Click(object sender, EventArgs e) { SendEmail(); } public void SendEmail() { try { MailMessage msg = new MailMessage("webteam", "webteam"); StringBuilder body = new StringBuilder(); body.AppendLine("An unexcepted error has occurred."); body.AppendLine(); body.AppendLine(ViewState["LastError"].ToString()); msg.Subject = "Error"; msg.Body = body.ToString(); msg.IsBodyHtml = false; SmtpClient smtp = new SmtpClient("exchangeserver"); smtp.Send(msg); } catch (Exception ex) { lblException.Text = ex.Message; } }
это связано с этими 2 темами ниже, я хочу получить как GetHtmlErrorMessage и сессии на странице ошибок.
сеанс равен нулю после ResponseRewrite
почему HttpContext.Сеанс null, когда redirectMode = ResponseRewrite
я попробовал и вижу решение, которое не нужно
Server.Transfer() or Response.Redirect()
во-первых: удалить ResponseRewrite в сеть.конфигурации
Web.конфигурации
<customErrors defaultRedirect="errorHandler.aspx" mode="On" />
Затем Глобальной.асакс
void Application_Error(object sender, EventArgs e) { if(Context.IsCustomErrorEnabled) { Exception ex = Server.GetLastError(); Application["TheException"] = ex; //store the error for later } }
затем errorHandler.aspx.cs
protected void Page_Load(object sender, EventArgs e) { string htmlErrorMessage = string.Empty ; Exception ex = (Exception)Application["TheException"]; string yourSessionValue = HttpContext.Current.Session["YourSessionId"].ToString(); //continue with ex to get htmlErrorMessage if(ex.GetHtmlErrorMessage() != null){ htmlErrorMessage = ex.GetHtmlErrorMessage(); } // continue your code }
ссылки
http://www.developer.com/net/asp/article.php/3299641/ServerTransfer-Vs-ResponseRedirect.htm
Я думаю, что у вас есть несколько вариантов здесь.
вы можете сохранить последнее исключение в сеансе и получить его со своей страницы пользовательских ошибок; или вы можете просто перенаправить на свою страницу пользовательских ошибок в событии Application_error. Если вы выберете последнее, вы хотите убедиться, что используете сервер.Метод передачи.
это сработало для меня. в MVC 5
в~\Global.asax
void Application_Error(object sender, EventArgs e) { FTools.LogException(); Response.Redirect("/Error"); }
в~\Controllers
создатьErrorController.cs
using System.Web.Mvc; namespace MVC_WebApp.Controllers { public class ErrorController : Controller { // GET: Error public ActionResult Index() { return View("Error"); } } }
в~\Models
создатьFunctionTools.cs
using System; using System.Web; namespace MVC_WebApp.Models { public static class FTools { private static string _error; private static bool _isError; public static string GetLastError { get { string cashe = _error; HttpContext.Current.Server.ClearError(); _error = null; _isError = false; return cashe; } } public static bool ThereIsError => _isError; public static void LogException() { Exception exc = HttpContext.Current.Server.GetLastError(); if (exc == null) return; string errLog = ""; errLog += "**********" + DateTime.Now + "**********\n"; if (exc.InnerException != null) { errLog += "Inner Exception Type: "; errLog += exc.InnerException.GetType() + "\n"; errLog += "Inner Exception: "; errLog += exc.InnerException.Message + "\n"; errLog += "Inner Source: "; errLog += exc.InnerException.Source + "\n"; if (exc.InnerException.StackTrace != null) { errLog += "\nInner Stack Trace: " + "\n"; errLog += exc.InnerException.StackTrace + "\n"; } } errLog += "Exception Type: "; errLog += exc.GetType().ToString() + "\n"; errLog += "Exception: " + exc.Message + "\n"; errLog += "\nStack Trace: " + "\n"; if (exc.StackTrace != null) { errLog += exc.StackTrace + "\n"; } _error = errLog; _isError = true; } } }
в~\Views
Создать ПапкуError
и в~\Views\Error
создатьError.cshtml
@using MVC_WebApp.Models @{ ViewBag.Title = "Error"; if (FTools.ThereIsError == false) { if (Server.GetLastError() != null) { FTools.LogException(); } } if (FTools.ThereIsError == false) { <br /> <h1>No Problem!</h1> } else { string log = FTools.GetLastError; <div>@Html.Raw(log.Replace("\n", "<br />"))</div> } }
если вы введете этот адресlocalhost/Error
как может быть вместо отображения ошибок, переменная ' log ' будет храниться в базе данных
источник: Microsoft ASP.Net