23

我希望將所有401錯誤重定向到自定義錯誤頁面。我最初在我的web.config中設置了以下條目。如何在Asp.Net Mvc 3中顯示自定義錯誤頁面?

<customErrors defaultRedirect="ErrorPage.aspx" mode="On"> 
    <error statusCode="401" redirect="~/Views/Shared/AccessDenied.aspx" /> 
</customErrors> 

使用IIS Express時,我收到股票IIS Express 401錯誤頁面。

如果我不使用IIS Express,返回空白頁面。使用谷歌瀏覽器的網絡選項卡來檢查響應,我看到雖然頁面爲空,但在標題中返回401狀態

我到目前爲止嘗試的是使用來自this SO answer的建議,因爲我使用的是IIS Express,但沒有無濟於事。我嘗試過使用組合<custom errors><httpErrors>但沒有運氣 - 標準錯誤或空白頁仍然顯示。

httpErrors部分看起來像這樣在基於the link的那一刻起above SO question(我還發現另一個非常promising answer但沒有運氣 - 空白響應)

<system.webServer> 
    <httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough" > 
    <remove statusCode="401" /> 
    <error statusCode="401" path="/Views/Shared/AccessDenied.htm" /> 
    </httpErrors> 

<!-- 
<httpErrors errorMode="Custom" 
      existingResponse="PassThrough" 
      defaultResponseMode="ExecuteURL"> 
     <remove statusCode="401" /> 
    <error statusCode="401" path="~/Views/Shared/AccessDenied.htm" 
     responseMode="File" /> 
</httpErrors> 
--> 
</system.webServer> 

我甚至修改applicationhost.config文件,並修改<httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath"><httpErrors lockAttributes="allowAbsolutePathsWhenDelegated">根據來自iis.net的信息。在我的努力過程中,我也設法按照another SO question中所述的方法偶然發現了這個錯誤。

如何在Asp.Net Mvc 3中顯示自定義錯誤頁面?

其他信息

下列控制器動作已經裝飾了Authorise屬性爲特定用戶。

[HttpGet] 
[Authorize(Users = "domain\\userXYZ")] 
public ActionResult Edit() 
{ 
    return GetSettings(); 
} 

[HttpPost] 
[Authorize(Users = "domain\\userXYZ")] 
public ActionResult Edit(ConfigurationModel model, IList<Shift> shifts) 
{ 
    var temp = model; 
    model.ConfiguredShifts = shifts; 
    EsgConsole config = new EsgConsole(); 

    config.UpdateConfiguration(model.ToDictionary()); 
    return RedirectToAction("Index"); 
} 
+0

我也想知道如何獲得自定義錯誤顯示(在我的情況下403錯誤) - 500錯誤工作正常... –

+0

作出一個小型圖書館,使這更容易。它是可用的:https://github.com/Buildstarted/Errlusion – Buildstarted

+1

只是想你可能有興趣看到這[SO帖子](http://stackoverflow.com/questions/6308186/custom-errors-not-working-with - iisexpress) – CBRRacer

回答

10

我從來沒有能夠得到一個web.config和MVC的CustomErrors一起玩好,所以我放棄了。我這樣做。

在Global.asax中:

protected void Application_Error() 
    { 
     var exception = Server.GetLastError(); 
     var httpException = exception as HttpException; 
     Response.Clear(); 
     Server.ClearError(); 
     var routeData = new RouteData(); 
     routeData.Values["controller"] = "Errors"; 
     routeData.Values["action"] = "General"; 
     routeData.Values["exception"] = exception; 
     Response.StatusCode = 500; 
     if (httpException != null) 
     { 
      Response.StatusCode = httpException.GetHttpCode(); 
      switch (Response.StatusCode) 
      { 
       case 403: 
        routeData.Values["action"] = "Http403"; 
        break; 
       case 404: 
        routeData.Values["action"] = "Http404"; 
        break; 
      } 
     } 
     // Avoid IIS7 getting in the middle 
     Response.TrySkipIisCustomErrors = true; 
     IController errorsController = new GNB.LG.StrategicPlanning.Website.Controllers.ErrorsController(); 
     HttpContextWrapper wrapper = new HttpContextWrapper(Context); 
     var rc = new RequestContext(wrapper, routeData); 
     errorsController.Execute(rc); 
    } 

在ErrorsController:

public class ErrorsController 
{ 
    public ActionResult General(Exception exception) 
    { 
     // log the error here 
     return View(exception); 
    } 

    public ActionResult Http404() 
    { 
     return View("404"); 
    } 

    public ActionResult Http403() 
    { 
     return View("403"); 
    } 
} 

在web.config中:

<customErrors mode="Off" /> 

這是爲我工作,無論在哪裏,錯誤是怎麼創建。 401現在不在那裏處理,但你可以很容易地添加它。

+1

感謝您的答覆 - 但是我已經看到了這種方法,出於某種原因,它並沒有吸引我。 – Ahmad

+1

@Ahmad我既不,但它的作品。 :)我發現試圖使用web.config中的CustomErrors進行設置,這取決於引發錯誤的位置/方式,它並不總是有效。 – Tridus

+1

好的答案 - 除了我還會在Application_Error的塊周圍添加if(!HttpContext.Current.IsDebuggingEnabled),以便在調試時仍顯示錯誤。 – NightOwl888

34

我使用以下步驟:

// in Global.asax.cs: 
     protected void Application_Error(object sender, EventArgs e) { 

      var ex = Server.GetLastError().GetBaseException(); 

      Server.ClearError(); 
      var routeData = new RouteData(); 
      routeData.Values.Add("controller", "Error"); 
      routeData.Values.Add("action", "Index"); 

      if (ex.GetType() == typeof(HttpException)) { 
       var httpException = (HttpException)ex; 
       var code = httpException.GetHttpCode(); 
       routeData.Values.Add("status", code); 
      } else { 
       routeData.Values.Add("status", 500); 
      } 

      routeData.Values.Add("error", ex); 

      IController errorController = new Kavand.Web.Controllers.ErrorController(); 
      errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData)); 
     } 

     protected void Application_EndRequest(object sender, EventArgs e) { 
      if (Context.Response.StatusCode == 401) { // this is important, because the 401 is not an error by default!!! 
       throw new HttpException(401, "You are not authorised"); 
      } 
     } 

AND:

// in Error Controller: 
    public class ErrorController : Controller { 

     public ActionResult Index(int status, Exception error) { 
      Response.StatusCode = status; 
      return View(status); 
     } 

     protected override void Dispose(bool disposing) { 
      base.Dispose(disposing); 
     } 
    } 

與在錯誤文件夾中的索引視圖:

@* in ~/Views/Error/Index.cshtml: *@ 

@model Int32  
@{ 
    Layout = null; 
}  
<!DOCTYPE html>  
<html> 
<head> 
    <title>Kavand | Error</title> 
</head> 
<body> 
    <div> 
     There was an error with your request. The error is:<br /> 
     <p style=" color: Red;"> 
     @switch (Model) { 
      case 401: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      case 403: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      case 404: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      case 500: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      //and more cases for more error-codes... 
      default: { 
        <span>Unknown error!!!</span> 
       } 
       break; 
     } 
     </p> 
    </div> 
</body> 
</html> 

AND -the最終步驟:

<!-- in web.config: --> 

<customErrors mode="Off"/> 
+0

這似乎工作,異常是煩人的調試時Windows身份驗證和我在服務器上測試時必須將httpErrors existingResponse =「PassThrough」添加到Web配置中。謝謝雖然.. –

+0

其投擲錯誤CS0151:開關表達式或案例標籤必須是布爾型,字符型,字符串型,整數型,枚舉型或相應的可以爲null的類型..help plz ?? – codespider

+0

這隻對調試時適用於我。我怎樣才能讓它在服務器上工作?我仍然可以看到服務器上的默認錯誤頁面。 IIS有錯誤頁面設置模式=關閉。 – Soenhay

9

也許我錯過了一些東西,但MVC有一個使用自定義錯誤的默認全球ErrorHandlerAttribute。這很好地解釋了here

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new HandleErrorAttribute()); 
} 

所有你需要做的是在config打開custom errors,然後設置自定義錯誤重定向,最好是靜態HTML文件(如果有錯誤與應用程序)。

<customErrors mode="On" defaultRedirect="errors.htm"> 
    <error statusCode="404" redirect="errors404.htm"/> 
</customErrors> 

如果您願意也可以指向自定義Controller來顯示錯誤。在下面的示例中,我剛剛使用默認路由到名爲ErrorController,其操作名爲Index,字符串參數名爲id(用於接收錯誤代碼)。你當然可以使用你想要的任何路由。您的示例不起作用,因爲您正嘗試直接鏈接到Views目錄,而不通過Controller。 MVC .NET不直接向Views文件夾提供請求。

<customErrors mode="On" defaultRedirect="/error/index/500"> 
    <error statusCode="404" redirect="/error/index/404"/> 
</customErrors> 

ErrorHandlerAttribute也可以Controllers/Actions廣泛用於重定向相關Controller錯誤命名Views。例如,以顯示View命名爲MyArgumentErrorArgumentException類型的異常發生時,你可以使用:

[ControllerAction,ExceptionHandler("MyArgumentError",typeof(ArgumentException))] 
public void Index() 
{ 
    // some code that could throw ArgumentExcepton 
} 

當然,另一種選擇是在Shared更新股票Error頁面。

+2

工作問題是,IIS Express已經處理了其他狀態代碼(不是500),所以你建議並不總是工作(取決於IIS設置)。 IIS只顯示它自己的頁面,而我們從來沒有在asp中看到它。 –

+0

的確,這只是IIS配置,但這是一個不同的問題。 MVC錯誤處理應該如上所述完成。 – TheCodeKing

0

看看你的web.config的第一部分,你直接指向一個.aspx頁面。當我設置我的錯誤頁面時,我直接指向了一個控制器和操作。例如:

<customErrors mode="On" defaultRedirect="~/Error/UhOh"> 
    <error statusCode="404" redirect="~/Error/NotFound" /> 
    <error statusCode="403" redirect="~/Error/AccessDenied" /> 
</customErrors> 

而且我有一個錯誤控制器,包含所有必需的操作。我不認爲MVC可以直接調用.aspx頁面。

+0

它可以和aspx頁面一起工作,事實上,如果你使用的是重寫模式,那麼你必須使用靜態內容文件(而不是動作) –

相關問題