ASP.NET page d'erreur personnalisée - Serveur.GetLastError () est null
j'ai une page d'erreur personnalisée établie pour mon application:
<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx"
/>
Dans Global.asax, Application_Error (), le code suivant fonctionne pour obtenir les détails de l'exception:
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.GetBaseException() != null)
ex = ex.GetBaseException();
}
au moment où j'arrive à ma page d'erreur (~/errors/GeneralError.aspx.cs), à un Serveur.GetLastError () est null
est-ce que je peux obtenir les détails de l'exception sur la Page D'erreur, plutôt que dans Global.asax.cs ?
ASP.NET 3.5 sur Vista / IIS7
10 réponses
regardant de plus près mon web.configuration de la configuration, un des commentaires dans ce message est très utile
in asp.net 3.5 sp1 il y a un nouveau paramètre redirectMode
pour que nous puissions modifier customErrors
pour ajouter ce paramètre:
<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />
le mode ResponseRewrite
nous permet de charger la" page D'erreur " sans rediriger le navigateur, de sorte que l'URL reste la même, et fait important pour moi, l'information d'exception n'est pas perdue.
OK, j'ai trouvé ce post: http://msdn.microsoft.com/en-us/library/aa479319.aspx
avec ce diagramme très illustratif:
diagramme http://i.msdn.microsoft.com/Aa479319.customerrors_01 (en-us,MSDN.10).gif
essentiellement, pour obtenir ces détails exceptionnels, je dois les stocker moi-même dans Global.asax, pour une récupération ultérieure sur ma page d'erreur personnalisée.
il semble que le meilleur moyen est de faire le gros du travail Mondial.asax, avec les pages d'erreur personnalisées traitant le contenu utile plutôt que la logique.
une combinaison de ce que NailItDown et Victor ont dit. La façon préférée / facile est d'utiliser votre Global.Asax pour stocker l'erreur et ensuite rediriger vers votre page d'erreur personnalisée.
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
}
En outre, vous devez configurer votre "151960920 web".config :
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/myErrorPage.aspx">
</customErrors>
</system.web>
et enfin, faire tout ce dont vous avez besoin à l'exception que vous avez stocké dans votre erreur page :
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 ...
}
essayez d'utiliser quelque chose comme Server.Transfer("~/ErrorPage.aspx");
de la méthode Application_Error()
de global.asax.cs
puis de l'intérieur de Page_Load()
D'ErrorPage.aspx.cs vous devriez être bien de faire quelque chose comme: Exception exception = Server.GetLastError().GetBaseException();
Server.Transfer()
semble garder l'exception traîner autour.
bien qu'il y ait plusieurs bonnes réponses ici, je dois souligner que ce n'est pas une bonne pratique d'Afficher des messages d'exception système sur les pages d'erreur (ce qui est ce que je suppose que vous voulez faire). Vous risquez de révéler des choses que vous ne souhaitez pas le faire à des utilisateurs malveillants. Par exemple, les messages D'exception Sql Server sont très verbeux et peuvent donner le nom d'utilisateur, le mot de passe et les informations de schéma de la base de données en cas d'erreur. Cette information ne doit pas être affichée à une fin utilisateur.
une considération importante que je pense que tout le monde manque ici est un scénario d'équilibrage de la charge (web farm). Depuis le serveur qui exécute global.asax peut être différent que le serveur qui est à propos de l'exécution de la page d'erreur personnalisée, le rangement de l'objet d'exception dans L'Application n'est pas fiable.
je suis toujours à la recherche d'une solution fiable à ce problème dans une configuration de ferme web, et/ou une bonne explication de MS quant à la raison pour laquelle vous ne pouvez tout simplement pas exception avec le serveur.GetLastError sur la page d'erreur personnalisée comme vous pouvez dans global.ASAX Application_Error.
P.S. il est dangereux de stocker des données dans la collection de L'Application sans d'abord les verrouiller et ensuite les déverrouiller.
voici ma solution..
Dans 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");
}
In 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;
}
}
ceci lié à ces 2 sujets ci-dessous, je veux obtenir à la fois GetHtmlErrorMessage et Session sur la page D'erreur.
Session is null after Responderewrite
pourquoi HttpContext.Session null quand redirectMode = Reponserewrite
j'ai essayé et voir la solution qui n'a pas besoin Server.Transfer() or Response.Redirect()
tout d'abord: supprimer la réponse sur le web.config
Web.config
<customErrors defaultRedirect="errorHandler.aspx" mode="On" />
Puis Mondial.asax
void Application_Error(object sender, EventArgs e)
{
if(Context.IsCustomErrorEnabled)
{
Exception ex = Server.GetLastError();
Application["TheException"] = ex; //store the error for later
}
}
puis 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
}
pour les références
http://www.developer.com/net/asp/article.php/3299641/ServerTransfer-Vs-ResponseRedirect.htm
je pense que vous avez plusieurs options.
vous pouvez stocker la dernière Exception dans la Session et la récupérer à partir de votre page d'erreur personnalisée; ou vous pouvez simplement rediriger vers votre page d'erreur personnalisée dans L'événement Application_error. Si vous choisissez ce dernier, vous voulez vous assurer d'utiliser le serveur.Méthode de transfert.
ça a marché pour moi. dans MVC 5
in ~\Global.asax
void Application_Error(object sender, EventArgs e)
{
FTools.LogException();
Response.Redirect("/Error");
}
dans ~\Controllers
créer ErrorController.cs
using System.Web.Mvc;
namespace MVC_WebApp.Controllers
{
public class ErrorController : Controller
{
// GET: Error
public ActionResult Index()
{
return View("Error");
}
}
}
dans ~\Models
créer 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;
}
}
}
dans ~\Views
créer un dossier Error
et dans ~\Views\Error
créer 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>
}
}
si vous inscrivez cette adresse localhost/Error
comme peut l'être au lieu d'Afficher des erreurs, variable 'log' à stocker dans la base de données
Source: Microsoft ASP.Net