114

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

<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.cs) 时,Server.GetLastError() 为空

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

Vista/IIS7 上的 ASP.NET 3.5

4

10 回答 10

137

仔细查看我的 web.config 设置,这篇文章中的一条评论非常有帮助

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

所以我们可以修改customErrors添加这个参数:

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

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

于 2008-12-05T06:33:14.157 回答
38

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

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

图表
(来源:microsoft.com

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

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

于 2008-12-05T06:23:32.850 回答
18

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

全球.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 ...
}
于 2008-12-05T19:29:30.610 回答
6

尝试在global.asax.csServer.Transfer("~/ErrorPage.aspx");的方法中使用类似的东西Application_Error()

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

Server.Transfer()似乎保持异常徘徊。

于 2009-04-23T04:27:36.150 回答
5

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

于 2011-06-07T20:39:08.660 回答
5

这是我的解决方案..

在 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;
        }
    }
于 2011-09-28T16:03:16.633 回答
4

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

我仍在寻找一个可靠的解决方案来解决这个问题在 global.asax Application_Error 中。

PS 如果不先锁定再解锁,将数据存储在Application集合中是不安全的。

于 2010-06-05T20:23:01.563 回答
3

它对我有用。在 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~\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 打开页面没有错误



如果发生错误 发生错误

可以代替显示错误,将变量“日志”存储在数据库中


来源:微软 ASP.Net

于 2017-01-22T02:37:24.393 回答
2

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

ResponseRewrite 后会话为空

为什么当 redirectMode = ResponseRewrite 时 HttpContext.Session 为空

我试过并看到不需要的解决方案Server.Transfer() or Response.Redirect()

第一:去掉web.config中的ResponseRewrite

网页配置

<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

于 2016-12-15T13:06:01.190 回答
1

我想你在这里有几个选择。

您可以将最后一个异常存储在 Session 中并从您的自定义错误页面中检索它;或者您可以在 Application_error 事件中重定向到您的自定义错误页面。如果选择后者,则要确保使用 Server.Transfer 方法。

于 2008-12-05T19:05:15.417 回答