簡體   English   中英

ASP.NET MVC自定義錯誤

[英]ASP.NET MVC Custom Errors

我的目標是在應用程序中創建一個處理所有托管錯誤的錯誤處理,而不僅僅是與MVC相關。 所以我沒有使用HandleErrorAttribute模式,因為它僅用於MVC錯誤,而不是其他托管錯誤。

在我的Global.asax中,我有:

protected void Application_Error()
{
    string displayError = ConfigurationManager.AppSettings["DisplayError"];
    NameValueCollection serverVariables;
    int loop1, loop2;
    StringBuilder serverVariableKeys = new StringBuilder();
    Exception exception = Server.GetLastError();
    HttpException httpException = exception as HttpException;

    if (HttpContext.Current != null)
    {
            // loop through and get server vars
    }

    if (exception != null)
        // Log Error

    // Redirect to Error page if set to basic mode
    if (!string.IsNullOrWhiteSpace(displayError) && displayError.ToLower() == "basic")
    {
        Response.Clear();
    Server.ClearError(); // needed for redirect to work

    var routeData = new RouteData();
    routeData.Values["controller"] = "Error";
    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;
        }
    }

    IController errorsController = new Controllers.ErrorController();
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
    errorsController.Execute(rc);
    }
}

我有一個ErrorController ,它有GeneralHttp403Http404 Actions。 我有與每個動作相對應的視圖。

在我的web.config中,我有:

  <system.web>  
    <!-- removed bits to reduce space -->
    <customErrors mode="On" />
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules >
      <remove name="UrlRoutingModule-4.0" />
      <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
      <remove name="Session"/>
      <add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition=""/>
    </modules>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <httpErrors errorMode="Detailed" />
  </system.webServer>

這適用於與托管代碼相關的許多方案,但是當IIS接管時,例如錯誤的靜態文件調用(example.com/BadFileName.gif),它將從IIS返回錯誤,該錯誤揭示了服務器詳細信息,例如本地文件路徑。 這是因為web.config中的以下行:

<httpErrors errorMode="Detailed" />

但是當我將errorMode設置為其他值(如Custom)或只刪除該行時,我的自定義錯誤處理將停止運行,並且會返回包含托管代碼錯誤在內的所有內容的默認IIS錯誤消息。

我已經嘗試了很多東西來獲得自定義錯誤,沒有這個設置就沒有運氣,包括:

  • CustomError設置為mode="Off"
  • customError下定義Error節點以重定向到我的控制器
  • httpErrors下定義Error節點以重定向到我的控制器

當我逐步調試時,我可以看到對控制器的調用,但最后IIS發送了響應。 錯誤日志記錄確實被正確調用Application_Error,因此代碼確實允許應用程序處理它到某一點。

申請細節:

  • ASP.NET MVC 4.0
  • IIS 7.5(Azure網站預覽版)上托管

有沒有辦法不使用<httpErrors errorMode="Detailed" />並使其工作?

您看到該行為的原因可能是您正在調用Application_Error處理程序(並調用您的控制器),但是IIS正在攔截500錯誤並顯示其自己的錯誤頁面。 (盡管你的Application_Error處理程序本身也可能拋出一個Exception ,這是你要排除的東西)

因為您想要處理所有錯誤(例如您提到的靜態文件錯誤),您可能無法依賴ASP.NET或ASP.NET MVC為您執行初始錯誤檢測。 並非所有錯誤都來自您的應用程序!

最好的辦法是盡可能地依靠IIS 7.5的錯誤處理,而不是試圖過早介入。 讓IIS為您執行初始錯誤檢測,這樣更容易。

嘗試將以下內容放入web.config ,替換現有的httpErrors節點: -

<httpErrors errorMode="Custom" existingResponse="Replace">
  <clear />
  <error statusCode="400" responseMode="ExecuteURL" path="/Error" />
  <error statusCode="403" responseMode="ExecuteURL" path="/Error/Forbidden" />
  <error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
  <error statusCode="500" responseMode="ExecuteURL" path="/Error" />
</httpErrors>

完全刪除customErrors節點。 這是不必要的。

記住並確保您的錯誤控制器正在設置正確的狀態代碼: -

public ActionResult Forbidden()
{
    Response.StatusCode = 403;
    return this.View();
}

然后,除了注銷Application_Error處理程序之外,您應該能夠拋棄所有內容 - 盡管我認為您最好創建自己的HttpModule ; web.config的modules節點上設置runAllManagedModulesForAllRequests可以幫助您捕獲否則會runAllManagedModulesForAllRequests的錯誤。

我已經在Azure網站預覽版上運行了這個設置(雖然我個人使用elmah進行日志記錄),並且除了顯然因未能解析web.config而導致的任何錯誤之外,它正在捕獲所有內容。

在github上提供了一個完整的工作示例,使用httpErrors來自定義錯誤頁面 您也可以在天藍色的網站上看到它

如果你想在你的應用程序中處理這個,你可以編寫一個自定義處理程序或使用HandleError屬性是一個很好的例子來解決這個問題,而不必使用IIS作為拐杖。 因為並非所有IIS主機提供商都允許在服務器級別進行此類自定義,並且IMO是一種不好的方法,因為它在部署時創建了額外的配置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM