webentwicklung-frage-antwort-db.com.de

Benutzerdefinierte ASP.NET-Fehlerseite - Server.GetLastError () ist null

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

110
nailitdown

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.

136
nailitdown

OK, ich habe diesen Beitrag gefunden: http://msdn.Microsoft.com/en-us/library/aa479319.aspx

mit diesem sehr anschaulichen Diagramm:

diagram
(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.

36
nailitdown

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 ...
}
18
rlb.usa

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;
        }
    }
5
user825345

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.

5
Phil

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.

4
Leonard Lobel

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

2
Bao

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/Erroropen page Whithout Error



Und wenn ein Fehler auftritt error occurs

Anstatt Fehler anzuzeigen, kann auch die Variable 'log' in der Datenbank gespeichert werden


Quelle: Microsoft ASP.Net

2
M.R.T2017

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.

1
Victor