Ich habe eine benutzerdefinierte Fehlerseite für meine Anwendung eingerichtet:
<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx"
/>
In Global.asax, Application_Error (), funktioniert der folgende Code, um die Ausnahmedetails abzurufen:
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.GetBaseException() != null)
ex = ex.GetBaseException();
}
Wenn ich meine Fehlerseite (~/errors/GeneralError.aspx.cs) erreiche, ist Server.GetLastError () null
Gibt es eine Möglichkeit, die Ausnahmedetails auf der Fehlerseite anstatt in Global.asax.cs abzurufen?
ASP.NET 3.5 unter Vista/IIS7
Bei genauerer Betrachtung meiner web.config-Einrichtung ist einer der Kommentare in dieser Beitrag ist sehr hilfreich
in asp.net 3.5 sp1 gibt es einen neuen parameter redirectMode
Also können wir customErrors
ändern, um diesen Parameter hinzuzufügen:
<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />
der ResponseRewrite
-Modus ermöglicht es uns, die "Fehlerseite" zu laden, ohne den Browser umzuleiten, sodass die URL gleich bleibt und für mich wichtig ist, dass Ausnahmeinformationen nicht verloren gehen.
OK, ich habe diesen Beitrag gefunden: http://msdn.Microsoft.com/en-us/library/aa479319.aspx
mit diesem sehr anschaulichen Diagramm:
(Quelle: Microsoft.com )
um an diese Ausnahmedetails zu gelangen, muss ich sie im Wesentlichen selbst in Global.asax speichern, um sie später auf meiner benutzerdefinierten Fehlerseite abrufen zu können.
am besten erledigen Sie den Großteil der Arbeit in Global.asax, da die benutzerdefinierten Fehlerseiten eher hilfreichen Inhalt als Logik verarbeiten.
Eine Kombination von dem, was NailItDown und Victor gesagt haben. Die bevorzugte/einfachste Möglichkeit besteht darin, den Fehler mit Global.Asax zu speichern und dann zu Ihrer benutzerdefinierten Fehlerseite umzuleiten.
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
}
Außerdem müssen Sie Ihre web.config einrichten:
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/myErrorPage.aspx">
</customErrors>
</system.web>
Und schließlich tun Sie alles, was Sie brauchen, mit der Ausnahme, die Sie auf Ihrer Fehlerseite gespeichert haben :
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 ...
}
Hier ist meine Lösung ..
In Global.asax:
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;
}
}
Obwohl es hier mehrere gute Antworten gibt, muss ich darauf hinweisen, dass es nicht ratsam ist, Systemausnahmemeldungen auf Fehlerseiten anzuzeigen (was ich voraussetze, dass Sie dies tun möchten). Sie können versehentlich Dinge offenlegen, die Sie nicht möchten, um böswilligen Benutzern. Beispielsweise sind SQL Server-Ausnahmemeldungen sehr ausführlich und können den Benutzernamen, das Kennwort und die Schemainformationen der Datenbank enthalten, wenn ein Fehler auftritt. Diese Informationen sollten einem Endbenutzer nicht angezeigt werden.
Eine wichtige Überlegung, die meiner Meinung nach hier allen fehlt, ist ein Lastausgleichsszenario (Webfarm). Da sich der Server, auf dem global.asax ausgeführt wird, möglicherweise von dem Server unterscheidet, auf dem die benutzerdefinierte Fehlerseite ausgeführt wird, ist das Stashing des Ausnahmeobjekts in Application nicht zuverlässig.
Ich bin immer noch auf der Suche nach einer zuverlässigen Lösung für dieses Problem in einer Webfarmkonfiguration und/oder einer guten Erklärung von MS, warum Sie die Ausnahme mit Server.GetLastError nicht auf der benutzerdefinierten Fehlerseite wie möglich finden können in global.asax Application_Error.
P.S. Es ist nicht sicher, Daten in der Anwendungssammlung zu speichern, ohne sie zuerst zu sperren und dann zu entsperren.
Dies bezog sich auf diese 2 Themen unten, ich möchte sowohl GetHtmlErrorMessage als auch Session on Error Seite erhalten.
Sitzung ist nach ResponseRewrite null
Warum ist HttpContext.Session null, wenn redirectMode = ResponseRewrite
Ich habe versucht, eine Lösung zu finden, die Server.Transfer() or Response.Redirect()
nicht benötigt.
Zuerst: ResponseRewrite in web.config entfernen
Web.config
<customErrors defaultRedirect="errorHandler.aspx" mode="On" />
Dann Global.asax
void Application_Error(object sender, EventArgs e)
{
if(Context.IsCustomErrorEnabled)
{
Exception ex = Server.GetLastError();
Application["TheException"] = ex; //store the error for later
}
}
Dann 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
}
Für Referenzen
http://www.developer.com/net/asp/article.php/3299641/ServerTransfer-Vs-ResponseRedirect.htm
Es hat bei mir funktioniert. in MVC 5
im ~\Global.asax
void Application_Error(object sender, EventArgs e)
{
FTools.LogException();
Response.Redirect("/Error");
}
im ~\Controllers
Erstellen ErrorController.cs
using System.Web.Mvc;
namespace MVC_WebApp.Controllers
{
public class ErrorController : Controller
{
// GET: Error
public ActionResult Index()
{
return View("Error");
}
}
}
im ~\Models
Erstellen 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;
}
}
}
im ~\Views
Ordner erstellen Error
und in ~\Views\Error
Erstellen 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>
}
}
Wenn Sie diese Adresse eingeben localhost/Error
Quelle: Microsoft ASP.Net
Ich denke, Sie haben hier ein paar Möglichkeiten.
sie können die letzte Ausnahme in der Sitzung speichern und von Ihrer benutzerdefinierten Fehlerseite abrufen. Oder Sie können einfach zu Ihrer benutzerdefinierten Fehlerseite innerhalb des Application_error-Ereignisses umleiten. Wenn Sie sich für Letzteres entscheiden, möchten Sie sicherstellen, dass Sie die Server.Transfer-Methode verwenden.