NET 自定义错误页面-Server.GetLastError()为空

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

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

当我到达我的错误页面(~/error/ generalerror.aspx.cs )时,服务器

有没有什么办法可以让我在错误页面上得到异常的详细信息,而不是在 Global.asax.cs?

Vista/IIS7上的 ASP.NET 3.5

113480 次浏览

好吧,我发现了这个帖子: Http://msdn.microsoft.com/en-us/library/aa479319.aspx

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

diagram
(来源: Microsoft.com)

实际上,为了获得这些异常细节,我需要将它们存储在 Global.asax 中,以便稍后在我的自定义错误页面上检索。

it seems the best way is to do the bulk of the work in Global.asax, with the custom error pages handling helpful content rather than logic.

更仔细地查看我的 web.config 设置,这是 这篇文章很有帮助中的一条注释

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

因此,我们可以修改 customErrors来添加这个参数:

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

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

我觉得你有很多选择。

您可以在 Session 中存储最后一个 Exception 并从自定义错误页面检索它; 或者您可以在 Application _ error 事件中重定向到自定义错误页面。如果选择后者,则需要确保使用服务器。转账方式。

结合了 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 ...
}

尝试在 global.asax.cs 的 Application_Error()方法中使用类似于 Server.Transfer("~/ErrorPage.aspx");的内容

然后从 errorpage.aspx.cs 的 Page_Load()开始,你应该可以做类似于: Exception exception = Server.GetLastError().GetBaseException();的动作

Server.Transfer()似乎仍然保留着异常。

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

我仍然在寻找一个可靠的解决方案,在一个网络农场配置的问题,和/或一个很好的解释,从 MS 为什么你只是不能拿起服务器异常。在自定义错误页面上的 GetLastError,就像 global.asax Application _ Error 中一样。

附注: 在 Application 集合中存储数据而不先锁定它,然后再解锁它是不安全的。

虽然这里有几个不错的答案,但是我必须指出,在错误页面上显示系统异常消息并不是一个好的做法(我假设您希望这样做)。您可能会在不经意间向恶意用户透露您不希望这样做的内容。例如,SqlServer 异常消息非常详细,当发生错误时可以提供数据库的用户名、密码和架构信息。该信息不应显示给最终用户。

这是我的解决办法。

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

这与下面的两个主题相关,我希望同时获得 GetHtmlErrorMessage 和 Session on Error 页面。

在 ResponseRewrite 之后会话为空

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

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

首先: 在 web.config 中删除 ResponseRewrite

Web.config

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

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

在 MVC5里,我就是这么做的


~\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 open page Whithout Error



如果出现错误 error occurs

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


资料来源: 微软 ASP.Net