2009-11-10 72 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

相關問題