ASP.NET自定义错误页面 – Server.GetLastError()为空
我有一个自定义的错误页面为我的应用程序设置:
<customErrors mode="On" defaultRedirect="~/errors/GeneralError.aspx" />
在Global.asax,Application_Error(),下面的代码工作来获取exception详细信息:
Exception ex = Server.GetLastError(); if (ex != null) { if (ex.GetBaseException() != null) ex = ex.GetBaseException(); }
当我到达我的错误页面(〜/ errors / GeneralError.aspx.cs)时,Server.GetLastError()为null
有没有什么办法可以在错误页面上获取exception详细信息,而不是在Global.asax.cs中?
Vista / IIS7上的ASP.NET 3.5
仔细查看我的web.config设置, 这篇文章中的一条评论是非常有帮助的
在asp.net 3.5 SP1中有一个新的参数redirectMode
所以我们可以修改customErrors
来添加这个参数:
<customErrors mode="RemoteOnly" defaultRedirect="~/errors/GeneralError.aspx" redirectMode="ResponseRewrite" />
ResponseRewrite
模式允许我们在不redirect浏览器的情况下加载“错误页面”,所以URL保持不变,对我来说重要的是,exception信息不会丢失。
好的,我发现这篇文章: http : //msdn.microsoft.com/en-us/library/aa479319.aspx
有这个非常说明性的图表:
图表http://i.msdn.microsoft.com/Aa479319.customerrors_01(en-us,MSDN.10).gif
实质上,为了获取这些exception细节,我需要自己将其存储在Global.asax中,以便以后在自定义错误页面上进行检索。
看起来最好的办法是做Global.asax的大部分工作,用自定义的错误页面来处理有用的内容而不是逻辑。
NailItDown和Victor说的一个组合。 首选/最简单的方法是使用Global.Asax来存储错误,然后redirect到您的自定义错误页面。
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 ... }
尝试使用像Server.Transfer("~/ErrorPage.aspx");
来自global.asax.cs的Application_Error()
方法
然后从ErrorPage.aspx.cs的Page_Load()
,你应该可以做类似的事情: Exception exception = Server.GetLastError().GetBaseException();
Server.Transfer()
似乎保持例外悬而未决。
虽然在这里有几个很好的答案,但我必须指出,在错误页面上显示系统exception消息是不好的做法(这正是我所假设的你想要做的)。 您可能会不经意地向恶意用户泄露您不希望这样做的内容。 例如,Sql Serverexception消息非常详细,可以在发生错误时给出数据库的用户名,密码和模式信息。 该信息不应该显示给最终用户。
我认为每个人都缺less的一个重要的考虑因素是负载平衡(web farm)scheme。 由于执行global.asax的服务器可能与执行自定义错误页面的服务器不同,因此在Application中隐藏exception对象是不可靠的。
我仍然在寻找一个可靠的解决scheme,这个问题在网上服务器场configuration,和/或从MS很好的解释,为什么你不能在自定义错误页面上的Server.GetLastError拿起例外,就像你可以在global.asax Application_Error中。
PS将数据存储在应用程序集合中,而不先locking并解锁,这是不安全的。
这是我的解决scheme..
在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; } }
我想你在这里有几个select。
您可以将最后一个exception存储在会话中,并从您的自定义错误页面中检索它; 或者你可以redirect到Application_error事件中的自定义错误页面。 如果您select后者,则要确保使用Server.Transfer方法。
这与下面这两个主题有关,我想同时获取GetHtmlErrorMessage和Session on Error页面。
ResponseRewrite后会话为空
为什么当redirectMode = ResponseRewrite时HttpContext.Session为空
我试过,看到没有需要的解决schemeServer.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
它为我工作。 在MVC 5中
在~\Global.asax
void Application_Error(object sender, EventArgs e) { FTools.LogException(); Response.Redirect("/Error"); }
在~\Controllers
创buildErrorController.cs
using System.Web.Mvc; namespace MVC_WebApp.Controllers { public class ErrorController : Controller { // GET: Error public ActionResult Index() { return View("Error"); } } }
在~\Models
创buildFunctionTools.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
创build文件夹Error
并在~\Views\Error
创buildError.cshtml
@using MVC_WebApp.Models @{ ViewBag.Title = "خطا"; 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> } }
如果你input这个地址localhost/Error
如果发生错误
可以代替显示错误,将variables“log”存储在数据库中
资料来源: 微软ASP.Net