简体   繁体   English

ASP.NET MVC自定义错误

[英]ASP.NET MVC Custom Errors

My goal is to create an error handling within the application that handles all managed errors, not just MVC related. 我的目标是在应用程序中创建一个处理所有托管错误的错误处理,而不仅仅是与MVC相关。 So I'm not using the HandleErrorAttribute pattern because it is only for MVC errors, not other managed errors. 所以我没有使用HandleErrorAttribute模式,因为它仅用于MVC错误,而不是其他托管错误。

In my Global.asax I have: 在我的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);
    }
}

I have an ErrorController that has General , Http403 and Http404 Actions. 我有一个ErrorController ,它有GeneralHttp403Http404 Actions。 I have views that correspond to each action. 我有与每个动作相对应的视图。

In my web.config I have: 在我的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>

This works for many scenarios related to managed code, but when IIS takes over, such as bad static file call (example.com/BadFileName.gif) it will return an error from IIS that discloses server details such as local file path. 这适用于与托管代码相关的许多方案,但是当IIS接管时,例如错误的静态文件调用(example.com/BadFileName.gif),它将从IIS返回错误,该错误揭示了服务器详细信息,例如本地文件路径。 This is because of the following line in the web.config: 这是因为web.config中的以下行:

<httpErrors errorMode="Detailed" />

But when I set errorMode to other values such as Custom, or just remove the line, my custom error handling stops functioning and the default IIS errors messages are returned for everything including managed code errors. 但是当我将errorMode设置为其他值(如Custom)或只删除该行时,我的自定义错误处理将停止运行,并且会返回包含托管代码错误在内的所有内容的默认IIS错误消息。

I've tried a number of things to get to the Custom Errors to work without this setting without any luck, including: 我已经尝试了很多东西来获得自定义错误,没有这个设置就没有运气,包括:

  • Setting CustomError to mode="Off" CustomError设置为mode="Off"
  • Defining Error nodes under customError to redirect to my controllers customError下定义Error节点以重定向到我的控制器
  • Defining Error nodes under httpErrors to redirect to my controllers httpErrors下定义Error节点以重定向到我的控制器

When I step through in debugging I can see the call to the controller, but in the end IIS sends the response instead. 当我逐步调试时,我可以看到对控制器的调用,但最后IIS发送了响应。 The error logging does get called correctly Application_Error, so the code does let application handle it to certain point. 错误日志记录确实被正确调用Application_Error,因此代码确实允许应用程序处理它到某一点。

Application Details: 申请细节:

  • ASP.NET MVC 4.0 ASP.NET MVC 4.0
  • Hosted on IIS 7.5 (Azure Web Site Preview) IIS 7.5(Azure网站预览版)上托管

Is there way not use <httpErrors errorMode="Detailed" /> and make this work? 有没有办法不使用<httpErrors errorMode="Detailed" />并使其工作?

The reason you're seeing the behaviour is probably that your Application_Error handler is correctly being invoked (and invoking your controller), but then IIS is intercepting the 500 error and displaying its own error page. 您看到该行为的原因可能是您正在调用Application_Error处理程序(并调用您的控制器),但是IIS正在拦截500错误并显示其自己的错误页面。 (though it's also possible that your Application_Error handler is itself throwing an Exception , that's something you'll want to rule out) (尽管你的Application_Error处理程序本身也可能抛出一个Exception ,这是你要排除的东西)

Because you want to handle all errors (eg the static file error you mentioned), you will likely be unable to rely on either ASP.NET or ASP.NET MVC to do the initial error detection for you. 因为您想要处理所有错误(例如您提到的静态文件错误),您可能无法依赖ASP.NET或ASP.NET MVC为您执行初始错误检测。 Not all errors come from your application! 并非所有错误都来自您的应用程序!

The best thing to do is to lean on IIS 7.5's error handling as much as you can, rather than try to get involved yourself too early. 最好的办法是尽可能地依靠IIS 7.5的错误处理,而不是试图过早介入。 Let IIS do the initial error detection for you and it's much easier. 让IIS为您执行初始错误检测,这样更容易。

Try putting the following in your web.config , replacing your existing httpErrors node:- 尝试将以下内容放入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>

Remove the customErrors node entirely. 完全删除customErrors节点。 It is unnecessary. 这是不必要的。

Remember and make sure your error controller is setting the correct status code:- 记住并确保您的错误控制器正在设置正确的状态代码: -

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

You should then be able to ditch everything apart from the logging out of your Application_Error handler - though I think you'd be best creating your own HttpModule ; 然后,除了注销Application_Error处理程序之外,您应该能够抛弃所有内容 - 尽管我认为您最好创建自己的HttpModule ; setting runAllManagedModulesForAllRequests on the modules node in your web.config helps you catch errors that would otherwise slip through. web.config的modules节点上设置runAllManagedModulesForAllRequests可以帮助您捕获否则会runAllManagedModulesForAllRequests的错误。

I've got this setup (though I'm personally using elmah to do the logging) running on the Azure Web Sites preview, and it's catching everything except from obviously any errors that come from failing to parse web.config . 我已经在Azure网站预览版上运行了这个设置(虽然我个人使用elmah进行日志记录),并且除了显然因未能解析web.config而导致的任何错误之外,它正在捕获所有内容。

I've put a full working example of using httpErrors for custom error pages up on github . 在github上提供了一个完整的工作示例,使用httpErrors来自定义错误页面 You can also see it live on azure web sites . 您也可以在天蓝色的网站上看到它

If you want to handle this in your app you can write a custom handler or use the HandleError Attribute here is a good example of one way to approach this instead of having to use IIS as a crutch. 如果你想在你的应用程序中处理这个,你可以编写一个自定义处理程序或使用HandleError属性是一个很好的例子来解决这个问题,而不必使用IIS作为拐杖。 as not all IIS host providers will allow this type of customization at the server level and IMO is a bad way to approach since it creates extra configuration at deployment time. 因为并非所有IIS主机提供商都允许在服务器级别进行此类自定义,并且IMO是一种不好的方法,因为它在部署时创建了额外的配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM