代码之家  ›  专栏  ›  技术社区  ›  nailitdown

ASP。NET自定义错误页-服务器。GetLastError()为空

  •  115
  • nailitdown  · 技术社区  · 17 年前

    我为我的应用程序设置了一个自定义错误页面:

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

    在Global.asax的Application_Error()中,以下代码用于获取异常详细信息:

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

    当我到达错误页面(~/errors/GeneralError.aspx)时,服务器。GetLastError()为空

    有什么方法可以在错误页面上而不是在Global.asax.cs中获取异常详细信息吗?

    ASP。NET 3.5在Vista/IIS7上的应用

    10 回复  |  直到 17 年前
        1
  •  137
  •   Sergey Vyacheslavovich Brunov prodigitalson    9 年前

    更仔细地查看我的web.config设置 this post is very helpful

    在asp.net 3.5 sp1中,有一个新的参数redirectMode

    所以我们可以修改 customErrors 要添加此参数,请执行以下操作:

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

    这个 ResponseRewrite 模式允许我们在不重定向浏览器的情况下加载错误页面,因此URL保持不变,对我来说重要的是,异常信息不会丢失。

        2
  •  38
  •   Glorfindel Doug L.    6 年前

    好的,我找到了这篇文章: http://msdn.microsoft.com/en-us/library/aa479319.aspx

    用这个非常说明性的图表:

    diagram
    (来源: microsoft.com )

    本质上,为了获取这些异常详细信息,我需要自己将它们存储在Global.asax中,以便以后在我的自定义错误页面上检索。

    似乎最好的方法是在Global.asax中完成大部分工作,使用自定义错误页面处理有用的内容而不是逻辑。

        3
  •  18
  •   Paul Fleming    12 年前

    NailItDown和Victor所说的话的结合。首选/最简单的方法是使用您的Global。Asax存储错误,然后重定向到您的自定义错误页面。

    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
    }
    

    此外,您需要设置 web.config文件 :

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

    最后,做任何你需要做的事情,除了你存储在你的 错误页面 :

    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 ...
    }
    
        4
  •  6
  •   Ross Oliver Ross Oliver    16 年前

    尝试使用类似的东西 Server.Transfer("~/ErrorPage.aspx"); 从内部 Application_Error() global.asax.cs方法

    然后从内部 Page_Load() 对于ErrorPage.aspx.cs,您应该可以执行以下操作: Exception exception = Server.GetLastError().GetBaseException();

    Server.Transfer() 似乎总是有例外。

        5
  •  5
  •   Phil    14 年前

    虽然这里有几个很好的答案,但我必须指出,在错误页面上显示系统异常消息并不是一种好的做法(我假设你想这样做)。您可能会无意中向恶意用户透露您不希望这样做的事情。例如,Sql Server异常消息非常冗长,在发生错误时可以提供数据库的用户名、密码和架构信息。这些信息不应该显示给最终用户。

        6
  •  5
  •   Kirk It looks like    12 年前

    这是我的解决方案。。

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

    在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;
            }
        }
    
        7
  •  4
  •   Leonard Lobel    15 年前

    我认为这里每个人都缺少的一个重要考虑因素是负载平衡(web场)场景。由于执行global.asax的服务器可能与执行自定义错误页面的服务器不同,因此将异常对象隐藏在Application中是不可靠的。

    我仍在寻找一个可靠的解决方案来解决web场配置中的这个问题,和/或从MS那里得到一个很好的解释,说明为什么你不能在服务器上发现异常。在自定义错误页面上显示GetLastError,就像在global.asax Application_error中一样。

    P.S.在Application集合中存储数据而不先锁定再解锁是不安全的。

        8
  •  3
  •   M.R.T    7 年前

    它在MVC 5中为我工作


    在……里面 ~\Global.asax

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


    在……里面 ~\Controllers 创建 ErrorController.cs

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


    在……里面 ~\Models 创建 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;
            }
        }
    }
    


    在……里面 ~\Views 创建文件夹 Error 和in ~\Views\Error 创建 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>
        }
    }
    


    如果您输入此地址 localhost/Error open page Whithout Error



    如果发生错误 error occurs

    变量“log”可以存储在数据库中,而不是显示错误


    来源: Microsoft ASP.Net

        9
  •  2
  •   Community Mohan Dere    8 年前

    这与下面的这两个主题有关,我想在错误页面上同时获取GetHtmlErrorMessage和Session。

    Session is null after ResponseRewrite

    Why is HttpContext.Session null when redirectMode = ResponseRewrite

    我试着找到了不需要的解决方案 Server.Transfer() or Response.Redirect()

    首先:删除web.config中的ResponseRewrite

    web.config文件

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

    然后是Global.asax

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

    然后是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
                }
    

    供参考

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

        10
  •  1
  •   Victor    17 年前

    我认为你有几个选择。

    您可以将最后一个异常存储在会话中,并从自定义错误页面检索它;或者,您可以直接重定向到Application_error事件中的自定义错误页面。如果选择后者,则需要确保使用服务器。转账方式。