2012-12-12 146 views
11

當我的ASP.NET MVC 4應用程序發生錯誤時,我想根據錯誤類型爲用戶定製視圖。例如,未找到頁面或發生了異常(提供了有關該異常的一些用戶友好的詳細信息)。我已經檢查瞭如何在StackOverflow和其他在線資源上執行此操作的其他示例,但沒有任何答案適用於我。ASP.NET MVC 4 - 異常處理不工作

基本的[HandleError]屬性在VS2012中似乎不適用於以.NET 4.5爲目標的MVC 4應用程序。下面是代碼我在我家的控制器:

[HandleError] 
public ActionResult Index() 
{ 
    Response.TrySkipIisCustomErrors = true; //doesn't work with or without this 
    throw new NullReferenceException("Uh oh, something broke."); 
} 

它只是拋出一個異常,並且我希望默認的〜/共享/ Error.cshtml視圖,因爲[的HandleError]屬性的返回,但我得到的只是一個HTTP 500內部服務器錯誤,指示無法顯示該頁面。我檢查了我的web.config,不同的配置似乎表現出奇怪。在節,目前,它包含:

<customErrors mode="On" /> 

(我嘗試添加的defaultRedirect並用的customErrors模式=「關」以及但是沒有任何效果......無論是共享的錯誤觀點或如果我將customErrors模式更改爲off,那麼我可以看到異常詳細信息,因此我們可以正確地看到異常細節,因此它正確地拋出「呃哦,破壞了某些東西」的異常。

我也試過了向HomeController添加一個OnException處理程序,雖然我可以通過調試並看到OnException事件正在引發,但它沒有任何區別:

protected override void OnException(ExceptionContext filterContext) 
{ 
    base.OnException(filterContext); 
    filterContext.ExceptionHandled = true; 
    if (filterContext == null) 
    { 
     filterContext.Result = View("CustomError"); 
     return; 
    } 
    Exception e = filterContext.Exception; 
    // TODO: Log the exception here 
    ViewData["Exception"] = e; // pass the exception to the view 
    filterContext.Result = View("CustomError"); 
} 

我也試圖改變[的HandleError]指定一個觀點,但似乎並不要麼做任何事情:

[HandleError(View="CustomError")] 

任何幫助將非常感激。如果您需要更多詳細信息,請告訴我。

回答

4

我似乎記得你必須從非本地主機IP地址(通常是另一臺計算機)呼叫該頁面。它必須是基於IIS的服務器,而不是內置的開發服務器(所以IIS或IIS Express,但是必須將IIS Express配置爲外部訪問,這很痛苦)。

您實際上可以對其進行調試,您必須在調試計算機上配置本地服務器以接受外部請求,然後從遠程服務器調用本地服務器。

+1

即使我沒有在web.config中的任何地方使用'RemoteOnly',我的原始代碼看起來似乎是遠程工作的,只是不在本地!這對我來說非常驚奇。我必須在web.config的部分添加'',以便渲染視圖,但這似乎很正常。這使得本地調試變得更加困難,並且由於沒有使用'mode = RemoteOnly',所以看起來像一個bug。如果有人發現如何在本地工作,請告訴我。 (我可能會特別提出第二個問題。) –

1

嘗試添加以下屬性到customErrors標籤:

defaultRedirect="Error" 

此明確定義到查看MVC應將用戶重定向時拋出的錯誤,並且沒有視圖默認屬性中指定。當然,只有當Shared視圖文件夾中存在Error.cshtml時纔會起作用。

+0

我終於開始嘗試這些建議。它看起來像使用''返回了我的PageNotFound錯誤頁面,而不是來自共享錯誤視圖的內容,並且ViewData中沒有異常數據。我認爲這是因爲/錯誤實際上並不存在於服務器上,並且web.config不知道任何關於實際視圖的信息......但是當我修改了OnException處理程序以使用「錯誤」視圖時,導致與我一直看到的相同的HTTP 500錯誤,並且我不再看到PageNotFound頁面。 :( –

5

我也參加了閱讀SO的答案和各種博客帖子,試圖讓自定義錯誤頁面工作的一個無休止的無休止的旅程。下面是最後爲我工作的東西。

第一步是使用IIS Express進行調試,而不是使用內置的Cassini Web服務器來「保證」調試體驗將鏡像實時環境。

創建一個控制器來處理應用程序錯誤,併爲您將要處理的每個自定義錯誤添加一個操作。該操作應該執行任何日誌記錄,設置狀態碼並返回視圖。

public class ErrorsController : Controller 
{ 
    // 404 
    [HttpGet] 
    public ActionResult NotFound() 
    { 
     Response.StatusCode = (int)HttpStatusCode.NotFound; 
     return View(); 
    } 

    // I also have test actions so that I can verify it's working in production. 
    [HttpGet] 
    public ActionResult Throw404() 
    { 
     throw new HttpException((int)HttpStatusCode.NotFound, "demo"); 
    } 
} 

在web.config中配置customErrors部分以重定向到您的自定義錯誤操作。

<system.web> 
    <customErrors mode="RemoteOnly" defaultRedirect="Errors/InternalServerError"> 
     <error statusCode="400" redirect="Errors/BadRequest" /> 
     <error statusCode="403" redirect="Errors/Forbidden" /> 
     <error statusCode="404" redirect="Errors/NotFound" /> 
     <error statusCode="500" redirect="Errors/InternalServerError" /> 
    </customErrors> 

添加httpErrors部分system.webServer並設置errorMode到詳細web.config中。爲什麼這個作品對我來說是個謎,但這是關鍵。

<system.webServer> 
    <httpErrors errorMode="Detailed" /> 

將最後一個catchall路由添加到定義的路由,以將404指向自定義頁面。

  // catchall for 404s 
     routes.MapRoute(
      "Error", 
      "{*url}", 
      new {controller = "Errors", action = "NotFound"}); 

您可能還需要創建一個自定義HandleErrorAttribute並將其註冊爲一個全球性的過濾器來登錄500錯誤。

在開發(IIS Express)和生產(IIS7)環境中,這些步驟都適用於我。您需要更改customErrors mode="On"以查看開發中的效果。

+0

我檢查了,並從項目屬性>網站,它默認爲「使用本地IIS Web服務器」與IIS Express檢查。它會花費我一點,以檢查其餘。 –

+1

刪除我的捕獲全部路由404 ,修改web.config,創建ErrorsController,連接Errors/{Action}路徑,似乎並沒有像預期的那樣工作。就好像IIS服務器在這些狀態下沒有正確重定向到Errors/代碼出現了,導航到/Errors/,可以工作,但是當我設置Response.StatusCode的時候我沒有得到自定義頁面,如果我刪除了StatusCode,那麼我得到的是自定義頁面, t觸發其他未找到的路徑或異常( /等等)。我已經在本地和遠程測試 –

+0

如果找不到重定向的原因,那麼這種方法可能是可行的(前如果需要,它可能無法將實際異常傳遞給InternalServerError視圖以呈現自定義錯誤頁面)。 –

1

我面臨着類似的問題,並失去了一些時間,試圖弄清楚發生了什麼。所以,萬一其他人面臨類似的問題,這就是我的問題所在。

錯誤頁面正試圖使用​​我的_Layout頁面。只要確保Error.cshtml頁面有

@ { Layout = null; }