2009-11-10 49 views
15

我在与上一个ASP.NET MVC应用程序,我已经部署了我的共享主机上的自定义错误的问题不显示。我创建了一个ErrorController,并将以下代码添加到Global.asax中以捕获未处理的异常,将它们记录下来,然后将控制权转移给ErrorController以显示自定义错误。此代码是从here采取:ASP.NET MVC应用程序的自定义错误页,共享托管环境

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绝对是射击,因为日志记录工作正常,但不是我的显示自定义错误页,我得到了去爸爸通用的。从博客文章的标题中可以看出,上面的代码是从我看来的,我注意到它使用MVC框架的Release Candidate 2。在1.0中有什么改变,导致代码的最后一行无效?像往常一样works great on my machine

任何建议将不胜感激。

编辑:忘了提及我已经尝试了Web.config中的customErrors模式的所有3种可能性(Off,On和RemoteOnly)。无论此设置如何,结果都是相同

编辑2:我以前也有和无控制器类下,[HandleError]装修试了一下。

更新:我已经想通了,并固定在404。 Go Daddy的托管控制中心中的设置面板的一部分可以控制404行为,默认情况下显示其通用页面,显然这会覆盖任何Web.config设置。所以我的自定义404页面现在按预期显示。然而,500和503仍然不起作用。我有代码HomeController的抢内容的静态文本版本如果SQL Server抛出异常如下:

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中的静态文本文件的路径更改为测试Home View的503版本,我所取而代之的是仅包含“service unavailable”的页面。而已。没有自定义503消息与网站的外观和感觉。

没有人有改进的代码,可以帮助有什么建议?是否有助于向HttpResponse添加不同的头文件?还是Go Daddy强行劫持503s?

回答

29

我找到了解决方案,它非常简单。原来问题实际上是在IIS7中。虽然调试在Visual Studio这个问题,我看到了以前我没有注意到的HttpResponse对象的属性:

public bool TrySkipIisCustomErrors { get; set; } 

这导致我这打开了一个great blog post by Rick Strahl,另一个是关于angrypets.com离我最近的搜索引擎以及this question here on SO。这些链接解释血淋淋的细节比我好多了,但是从里克的帖子这句话捕捉它相当不错:

这里发生真正的混乱,因为错误是由 ASP.NET所困,但后来最终还是处理由IIS查看 500状态码并返回库存IIS错误页面。

它也似乎这种行为是特定于IIS7集成模式。从msdn

当在经典模式在IIS 7.0中运行TrySkipIisCustomErrors 属性的默认值是true。在集成模式下运行时,TrySkipIisCustomErrors属性的缺省值为false。

所以基本上都是我最后不得不做的是设置Response.StatusCode到500或503和现在的一切功能设计的任何代码之后添加Response.TrySkipIisCustomErrors = true;

+1

+1谢谢,布莱恩。经过2个半小时的搜索,你给了我我需要的答案。它非常简单。我试图设置一个404错误代码,它给了我一个安全异常和“Response.TrySkipIisCustomErrors = true;”修复。 – 2009-12-31 19:48:48

+2

这让我疯狂。非常感谢。放置“Response.TrySkipIisCustomErrors = true;”在我的错误控制器中设置响应代码后立即对我有效。这是误导,因为我的本地IIS 7实例呈现我的自定义错误视图,但远程登台服务器不是。 = P – NovaJoe 2010-09-20 22:33:35

+0

应用此答案中提供的内容后,我在同一条船上:http://stackoverflow.com/a/7499406/114029。 'Response.TrySkipIisCustomErrors = true;'来自天堂! :) – 2012-07-31 21:13:17

0

我主办GoDaddy的一个ASP.NET MVC的网站,处理自定义错误页也面临问题。我发现,通过试验和错误,GoDaddy在HTTP级别拦截错误。

例如,它返回的404 HTTP状态代码导致G​​oDaddy的自定义错误页接管任何页面。最终我改变了我的自定义错误页面以返回200状态,404相关的问题消失了。我的HTML是一样的,只是需要改变的HTTP状态。

我承认从来没有尝试过对503状态响应做同样的事情,但可能会出现同样的缓解措施。如果您从返回503状态更改为返回200状态,问题是否消失?

请注意,如果您采取这种解决方法,您需要阻止搜索引擎将您的错误页面编入索引,然后返回200状态从常规页面无法区分(从搜索引擎的角度来看)。因此,请确保添加META ROBOTS标记,以防止为您的错误页面编制索引,例如

<META NAME="ROBOTS" CONTENT="NOINDEX"> 

这种方法的缺点可能是您的网页可能会从Google删除,这绝对不是一件好事!

UPDATE:因此,此外,还可以检测用户代理是否是履带或没有,如果它是一个履带返回503,而如果它不是一个爬虫,返回一个200见this blog post的信息关于如何检测爬虫。是的,我知道将不同的内容返回给抓取者与用户是一种搜索引擎优化禁忌,但是我已经在多个网站上完成了此操作,目前没有任何不良影响,所以我不确定问题的严重程度。

做这两种方法(META ROBOTS和机器人检测)可能是你最好的选择,以防奇怪的爬行者滑过机器人探测器。

+0

谢谢贾斯汀。我终于想出了如何修复404s,看到我上面的更新。在我的情况下,这种方法的问题是503中的一些将在实际的内容页面上显示友好的消息。如果我返回的是200而不是503,并且运气不够,目前没有任何抓取工具索引,他们会将我友好的错误消息而不是正确的内容编入索引。所以这不适用于我的特殊情况。感谢您的回复。 – Bryan 2009-11-11 01:57:41

+0

是的,得注意爬行者。我在原文中提到,你可以使用ROBOTS META标签来解决这个问题,但我也增加了更多的细节。往上看。 – 2009-11-11 04:01:16

+0

你可能没有看到任何不良影响,但是没有办法知道这对我和我的客户也是如此:-)。我很犹豫是否考虑你的方法,因为它可能会导致我的客户,并且由此我被移除和/或被禁止进入搜索引擎索引。 – Bryan 2009-11-11 21:47:59

相关问题