Página de error personalizado de ASP.NET – Server.GetLastError () es nulo

Tengo una página de error personalizada configurada para mi aplicación:

 

En Global.asax, Application_Error (), el siguiente código funciona para obtener los detalles de la excepción:

  Exception ex = Server.GetLastError(); if (ex != null) { if (ex.GetBaseException() != null) ex = ex.GetBaseException(); } 

Para cuando llego a mi página de error (~ / errors / GeneralError.aspx.cs), Server.GetLastError () es nulo

¿Hay alguna forma de que pueda obtener los detalles de la excepción en la página de error, en lugar de en Global.asax.cs?

ASP.NET 3.5 en Vista / IIS7

Mirando más de cerca mi configuración de web.config, uno de los comentarios en esta publicación es muy útil

en asp.net 3.5 sp1 hay un nuevo parámetro redirectMode

Entonces podemos modificar customErrors para agregar este parámetro:

  

el modo ResponseRewrite nos permite cargar la «Página de error» sin redirigir el navegador, por lo que la URL se mantiene igual, y lo que es más importante para mí, la información de excepción no se pierde.

OK, encontré esta publicación: http://msdn.microsoft.com/en-us/library/aa479319.aspx

con este diagtwig muy ilustrativo:

diagtwig http://i.msdn.microsoft.com/Aa479319.customerrors_01(en-us,MSDN.10).gif

en esencia, para obtener esos detalles de excepción, necesito almacenarlos en Global.asax, para su posterior recuperación en mi página de error personalizada.

parece que la mejor manera es hacer la mayor parte del trabajo en Global.asax, con las páginas de error personalizadas manejando el contenido útil en lugar de la lógica.

Una combinación de lo que dijeron NailItDown y Victor. La forma preferida / más fácil es usar su Global.Asax para almacenar el error y luego redireccionar a su página de error personalizada.

Global.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 } 

Además, debe configurar su web.config :

      

Y finalmente, haga lo que necesite con la excepción que ha almacenado en su página de error :

 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 ... } 

Intente usar algo como Server.Transfer("~/ErrorPage.aspx"); desde dentro del método Application_Error() de global.asax.cs

Entonces desde dentro de Page_Load() de ErrorPage.aspx.cs debería estar bien hacer algo como: Exception exception = Server.GetLastError().GetBaseException();

Server.Transfer() parece mantener la excepción dando vueltas.

Si bien hay varias buenas respuestas aquí, debo señalar que no es una buena práctica mostrar mensajes de excepción del sistema en páginas de error (que es lo que supongo que quiere hacer). Puede revelar inadvertidamente cosas que no desea hacer a usuarios malintencionados. Por ejemplo, los mensajes de excepción de servidor Sql son muy detallados y pueden proporcionar el nombre de usuario, la contraseña y la información de esquema de la base de datos cuando se produce un error. Esa información no se debe mostrar a un usuario final.

Una consideración importante que creo que todos faltan aquí es un escenario de balanceo de carga (granja de servidores web). Dado que el servidor que está ejecutando global.asax puede ser diferente del servidor que se trata de ejecutar la página de error personalizada, ocultar el objeto de excepción en la aplicación no es confiable.

Todavía estoy buscando una solución confiable a este problema en una configuración de granja de servidores web, y / o una buena explicación de MS sobre por qué simplemente no puede recoger la excepción con Server.GetLastError en la página de error personalizado como puede en global.asax Application_Error.

PD. No es seguro almacenar datos en la colección de aplicaciones sin antes bloquearlo y luego desbloquearlo.

Aquí está mi solución …

En Global.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"); } 

En Oops.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; } } 

Esto se relaciona con estos 2 temas a continuación, quiero obtener la página GetHtmlErrorMessage y Session on Error.

La sesión es nula después de ResponseRewrite

¿Por qué es HttpContext.Session null cuando redirectMode = ResponseRewrite

Intenté y vi una solución que no necesita Server.Transfer() or Response.Redirect()

Primero: elimine ResponseRewrite en web.config

Web.config

  

Entonces Global.asax

  void Application_Error(object sender, EventArgs e) { if(Context.IsCustomErrorEnabled) { Exception ex = Server.GetLastError(); Application["TheException"] = ex; //store the error for later } } 

Luego 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 } 

Para referencias

http://www.developer.com/net/asp/article.php/3299641/ServerTransfer-Vs-ResponseRedirect.htm

Creo que tienes un par de opciones aquí.

podría almacenar la última excepción en la sesión y recuperarla de su página de error personalizada; o simplemente puede redireccionar a su página de error personalizada dentro del evento Application_error. Si eliges lo último, debes asegurarte de utilizar el método Server.Transfer.

Funcionó para mí en MVC 5

en ~\Global.asax

 void Application_Error(object sender, EventArgs e) { FTools.LogException(); Response.Redirect("/Error"); } 

en ~\Controllers Create ErrorController.cs

 using System.Web.Mvc; namespace MVC_WebApp.Controllers { public class ErrorController : Controller { // GET: Error public ActionResult Index() { return View("Error"); } } } 

en ~\Models Create 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; } } } 

en ~\Views Crear Error carpeta y en ~\Views\Error Create Error.cshtml

 @using MVC_WebApp.Models @{ ViewBag.Title = "Error"; if (FTools.ThereIsError == false) { if (Server.GetLastError() != null) { FTools.LogException(); } } if (FTools.ThereIsError == false) { 

No Problem!

} else { string log = FTools.GetLastError;
@Html.Raw(log.Replace("\n", "
"))
} }

Si ingresas esta dirección localhost/Error abrir página sin error


Y si ocurre un error se produce un error

Como puede ser en lugar de mostrar errores, la variable ‘log’ se almacenará en la base de datos

Fuente: Microsoft ASP.Net