protected void Application_Error(object sender,EventArgs e) { Exception ex = Server.GetLastError(); Response.Clear(); HttpException httpEx = ex as HttpException; RouteData routeData = new RouteData(); routeData.Values.Add("controller","Error"); if (httpEx == null) { routeData.Values.Add("action","Index"); } else { switch (httpEx.GetHttpCode()) { case 404: routeData.Values.Add("action","HttpError404"); break; case 500: routeData.Values.Add("action","HttpError500"); break; case 503: routeData.Values.Add("action","HttpError503"); break; default: routeData.Values.Add("action","Index"); break; } } ExceptionLogger.LogException(ex); // <- This is working. Errors get logged routeData.Values.Add("error",ex); Server.ClearError(); IController controller = new ErrorController(); // The next line doesn't seem to be working controller.Execute(new RequestContext(new HttpContextWrapper(Context),routeData)); }
Application_Error肯定是发射,因为日志记录工作正常,但是不是显示我的自定义错误页面,我得到了Go Daddy通用的.从博客标题的上述代码取自,我注意到它使用了MVC框架的Release Candidate 2.在1.0中有什么改变,使最后一行代码不起作用?像往常一样works great on my machine.
任何建议将不胜感激.
编辑:忘了提到我已经尝试过Web.config中的customErrors模式的所有3个可能性(Off,On和RemoteOnly).与此设置相同的结果.
编辑2:我也尝试过和没有[HandleError]装饰的Controller类.
更新:我已经弄清楚了404s. Go Daddy的主机控制中心中有一部分“设置”面板,其中可以控制404行为,默认情况是显示其通用页面,显然这将覆盖任何Web.config设置.所以我的自定义404页面现在按照预期显示.然而,五百和五十三秒仍然没有工作.如果sql Server抛出异常,则HomeController中的代码将获取内容的静态文本版本,如下所示:
public ActionResult Index() { CcmDataClassesDataContext dc = new CcmDataClassesDataContext(); // This might generate an exception which will be handled in the OnException override HomeContent hc = dc.HomeContents.GetCurrentContent(); ViewData["bodyId"] = "home"; return View(hc); } protected override void OnException(ExceptionContext filterContext) { // Only concerned here with sqlExceptions so an HTTP 503 message can // be displayed in the Home View. All others will bubble up to the // Global.asax.cs and be handled/logged there. System.Data.sqlClient.sqlException sqlEx = filterContext.Exception as System.Data.sqlClient.sqlException; if (sqlEx != null) { try { ExceptionLogger.LogException(sqlEx); } catch { // couldn't log exception,continue without crashing } ViewData["bodyId"] = "home"; filterContext.ExceptionHandled = true; HomeContent hc = ContentHelper.GetStaticContent(); if (hc == null) { // Couldn't get static content. Display friendly message on Home View. Response.StatusCode = 503; this.View("ContentError").ExecuteResult(this.ControllerContext); } else { // Pass the static content to the regular Home View this.View("Index",hc).ExecuteResult(this.ControllerContext); } } }
public static HomeContent GetStaticContent() { HomeContent hc; try { string path = Configuration.CcmConfigSection.Config.Content.PathToStaticContent; string fileText = File.ReadAllText(path); string regex = @"^[^#]([^\r\n]*)"; MatchCollection matches = Regex.Matches(fileText,regex,RegexOptions.Multiline); hc = new HomeContent { ID = Convert.ToInt32(matches[0].Value),Title = matches[1].Value,DateAdded = DateTime.Parse(matches[2].Value),Body = matches[3].Value,IsCurrent = true }; } catch (Exception ex) { try { ExceptionLogger.LogException(ex); } catch { // couldn't log exception,continue without crashing } hc = null; } return hc; }
我已经验证,如果我更改连接字符串以生成sqlException,代码正确记录错误,然后抓取并显示静态内容.但是如果我也改变Web.config中静态文本文件的路径来测试503版本的Home View,那么我所得到的只是一个没有“服务不可用”的页面.而已.没有定制的503消息与网站的外观和感觉.
有没有人有任何建议改进代码可能有帮助?是否有助于向HttpResponse添加不同的头文件?还是去爸爸狠狠劫持503s?
解决方法
public bool TrySkipIisCustomErrors { get; set; }
这导致我到最近的搜索引擎,这个搜索引擎在angrypets.com和this question here on SO上发现了一个great blog post by Rick Strahl,而这些链接比我可以更好地解释了血腥细节,但是这个Rick的帖子引用得很好:
The real confusion here occurs because the error is trapped by
ASP.NET,but then ultimately still handled by IIS which looks at the
500 status code and returns the stock IIS error page.
在集成模式下,这种行为似乎也是IIS7特有的.从msdn:
When running in Classic mode in IIS 7.0 the TrySkipIisCustomErrors
property default value is true. When running in Integrated mode,the
TrySkipIisCustomErrors property default value is false.
所以基本上我最终都要做的是添加Response.TrySkipIisCustomErrors = true;在将Response.StatusCode设置为500或503的任何代码之后,所有内容都将按照设计进行功能.