ASP.NET MVC自定义错误

我的目标是在应用程序中创建一个处理所有托管错误的error handling,而不仅仅是与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中,我有:

                    

这适用于与托管代码相关的许多方案,但是当IIS接管时,例如错误的静态文件调用(example.com/BadFileName.gif),它将从IIS返回错误,该错误揭示了服务器详细信息,例如本地文件路径。 这是因为web.config中的以下行:

  

但是,当我将errorMode设置为其他值(如Custom)或只删除该行时,我的自定义error handling将停止运行,并返回包括托管代码错误在内的所有内容的默认IIS错误消息。

我已经尝试了很多东西来自定义错误,没有这个设置就没有运气,包括:

  • CustomError设置为mode="Off"
  • customError下定义Error节点以重定向到我的控制器
  • httpErrors下定义Error节点以重定向到我的控制器

当我逐步调试时,我可以看到对控制器的调用,但最后IIS发送了响应。 错误日志记录确实被正确调用Application_Error,因此代码确实允许应用程序处理它到某一点。

申请细节:

  • ASP.NET MVC 4.0
  • IIS 7.5上托管(Azure网站预览)

有没有办法不使用并使其工作?

您看到该行为的原因可能是您正在调用Application_Error处理程序(并调用您的控制器),但是IIS正在拦截500错误并显示其自己的错误页面。 (尽管你的Application_Error处理程序本身也可能抛出Exception ,这是你想要排除的东西)

因为您想要处理所有错误(例如您提到的静态文件错误),您可能无法依赖ASP.NET或ASP.NET MVC为您执行初始错误检测。 并非所有错误都来自您的应用程序!

最好的办法是尽可能地依靠IIS 7.5的error handling,而不是试图过早介入。 让IIS为您执行初始错误检测,这样更容易。

尝试将以下内容放在web.config ,替换现有的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来自定义错误页面 。 您也可以在azure色的网站上看到它 。

如果你想在你的应用程序中处理这个,你可以编写一个自定义处理程序或使用HandleError属性这是一个很好的例子来解决这个问题,而不必使用IIS作为拐杖。 因为并非所有IIS主机提供商都允许在服务器级别进行此类自定义,并且IMO是一种不好的方法,因为它在部署时创建了额外的配置。