Question

J'ai une page d'erreur personnalisée configurée pour mon application:

<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx"
/>

Dans Global.asax, Application_Error (), le code suivant permet d'obtenir les détails sur 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), Server.GetLastError () est null

Puis-je 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

Était-ce utile?

La solution

Si je regarde de plus près ma configuration web.config, l'un des commentaires de ce message est très utile

  

il existe un nouveau paramètre redirectMode dans asp.net 3.5 sp1

Nous pouvons donc modifier customErrors pour ajouter ce paramètre:

<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />

le mode ResponseRewrite nous permet de charger la & # 171; page d'erreur & # 187; sans rediriger le navigateur, l'URL reste donc la même et, ce qui est important pour moi, les informations sur les exceptions ne sont pas perdues.

Autres conseils

OK, j'ai trouvé ce post: http://msdn.microsoft.com/en-us/library/aa479319. aspx

avec ce diagramme très illustratif:

 diagramme
(source: microsoft.com )

En gros, pour obtenir ces détails sur les exceptions, je dois les stocker moi-même dans Global.asax, pour pouvoir les récupérer ultérieurement sur ma page d'erreur personnalisée.

il semble que le meilleur moyen consiste à effectuer l'essentiel du travail dans Global.asax, les pages d'erreur personnalisées permettant de gérer un contenu utile plutôt que logique.

Une combinaison de ce que NailItDown et Victor ont dit. La méthode préférée / la plus simple consiste à utiliser votre Global.Asax pour stocker l'erreur, puis à la 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
}

De plus, vous devez configurer votre web.config :

.
  <system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="~/myErrorPage.aspx">
    </customErrors>
  </system.web>

Enfin, faites tout ce dont vous avez besoin, à l'exception de celle que vous avez enregistrée dans votre page d'erreur :

.
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"); à partir de la méthode Application_Error () de global.asax.cs

Ensuite, à partir de Page_Load () de ErrorPage.aspx.cs, vous devriez pouvoir faire quelque chose comme: Exception exception = Server.GetLastError (). GetBaseException ();

Server.Transfer () semble garder l'exception à la traîne.

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 (c'est ce que je suppose que vous voulez faire). Vous pouvez révéler par inadvertance des choses que vous ne souhaitez pas faire à des utilisateurs malveillants. Par exemple, les messages d'exception de Sql Server sont très détaillés 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. Ces informations ne doivent pas être affichées pour un utilisateur final.

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

Dans 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;
        }
    }

Un facteur important qui, à mon avis, manque à tout le monde ici est le scénario d'équilibrage de la charge (batterie de serveurs Web). Étant donné que le serveur qui exécute global.asax peut être différent de celui sur lequel est exécutée la page d'erreur personnalisée, le stockage de l'objet exception dans Application n'est pas fiable.

Je cherche toujours une solution fiable à ce problème dans une configuration de batterie de serveurs Web et / ou une bonne explication de la part de MS qui explique pourquoi vous ne pouvez pas capturer l'exception avec Server.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 d'applications sans d'abord les verrouiller, puis les déverrouiller.

Ceci concerne les 2 sujets ci-dessous, je souhaite obtenir à la fois GetHtmlErrorMessage et la session sur la page d'erreur.

La session est nulle après ResponseRewrite

Pourquoi est-ce que HttpContext.Session est null quand redirectMode = ResponseRewrite

J'ai essayé et j'ai trouvé une solution qui ne nécessite pas Server.Transfer () ou Response.Redirect ()

Tout d'abord: supprimez ResponseRewrite dans web.config

Config. Web

<customErrors defaultRedirect="errorHandler.aspx" mode="On" />

Then Global.asax

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

Ensuite, 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

Cela a fonctionné pour moi. dans MVC 5


dans ~ \ Global.asax

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


in ~ \ Controllers Créez 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 Erreur 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 entrez cette adresse localhost / Error page ouverte sans erreur


Et si une erreur se produit une erreur survient

Comme cela peut être au lieu d'afficher des erreurs, la variable 'log' à stocker dans la base de données


  

Source: Microsoft ASP.Net

Je pense que vous avez quelques options ici.

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 cette dernière option, vous voulez vous assurer que vous utilisez la méthode Server.Transfer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top