web.config httpErrors部分和WebAPI区域可以共存吗?

时间:2021-03-30 03:33:17

I have an ASP.net MVC 5 project that contains a WebAPI in a specific 'API' area. I have IIS7 error handling enabled in my web.config like this:

我有一个ASP.net MVC 5项目,其中包含特定“API”区域中的WebAPI。我在我的web.config中启用了IIS7错误处理,如下所示:

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="400" subStatusCode="-1" />
        <remove statusCode="404" subStatusCode="-1" />
        <remove statusCode="500" subStatusCode="-1" />
        <error statusCode="400" path="400.html" responseMode="File" />
        <error statusCode="404" path="404.html" responseMode="File" />
        <error statusCode="500" path="500.html" responseMode="File" />
    </httpErrors>
</system.webServer>

This displays friendly messages to the user of the MVC website when 404/500 etc. occur. My problem arises when specific (legitimate) status codes are returned from the WebAPI (e.g. 400 when `/api/token' is called). In these cases, the JSON content of the reponse is intercepted by IIS and my friendly message HTML is returned as the response instead of the original JSON from the WebAPI. Is it possible to exclude the 'API' area from IIS error handling? If this cannot be done, what is the correct solution for allowing ASP.net MVC website friendly messages and WebAPI JSON responses to coexist?

当发生404/500等时,这向MVC网站的用户显示友好消息。当从WebAPI返回特定(合法)状态代码时(例如,当调用`/ api / token'时为400),我的问题就出现了。在这些情况下,响应的JSON内容被IIS拦截,我的友好消息HTML作为响应返回,而不是来自WebAPI的原始JSON。是否可以从IIS错误处理中排除'API'区域?如果无法做到这一点,那么允许ASP.net MVC网站友好消息和WebAPI JSON响应共存的正确解决方案是什么?

1 个解决方案

#1


13  

After much reading and experimentation I found this combination of settings to work effectively:

经过大量的阅读和实验,我发现这种设置组合能够有效地发挥作用:

The Friendly Error Pages

One aspx and one html page for each response status code (here's mine):

每个响应状态代码的一个aspx和一个html页面(这是我的):

  • 404.aspx
  • 404.aspx
  • 404.html
  • 404.html
  • 500.aspx
  • 500.aspx
  • 500.html
  • 500.html

The only difference between the two pages is that the aspx pages contain the following lines:

两个页面之间的唯一区别是aspx页面包含以下行:

<% Response.StatusCode = 500 %>
<% Response.TrySkipIisCustomErrors = true %>

The first line sends the correct HTTP status code back to the client, and the second line attempts to persuade IIS that it doesn't need to handle the response itself.

第一行将正确的HTTP状态代码发送回客户端,第二行尝试说服IIS不需要自己处理响应。

Web.config Setup

Custom Errors should be on, or remoteonly, and point to the aspx files:

自定义错误应该打开或远程,并指向aspx文件:

<customErrors mode="On" defaultRedirect="500.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="404.aspx" />
</customErrors>

IIS custom errors should be on too, and point to the html files in the system.webServer section:

IIS自定义错误也应该打开,并指向system.webServer部分中的html文件:

<httpErrors errorMode="Custom" existingResponse="Auto">
  <remove statusCode="404" subStatusCode="-1" />
  <remove statusCode="500" subStatusCode="-1" />
  <error statusCode="404" path="404.html" responseMode="File" />
  <error statusCode="500" path="500.html" responseMode="File" />
</httpErrors>

The existingResponse="Auto" tells IIS to only return the friendly error pages if the SetStatus flag is set. Effectively this allows ASP.net to send back a custom response, its own custom error page from the customErrors section, or allow IIS to return the configured friendly error page.

如果设置了SetStatus标志,则existingResponse =“Auto”告诉IIS仅返回友好错误页面。实际上,这允许ASP.net从customErrors部分发回自定义响应,自己的自定义错误页面,或允许IIS返回配置的友好错误页面。

FilterConfig.cs Setup

A default ASP.net MVC/WebAPI project is configured with a HandleErrorAttribute filter that handles exceptions raised from actions and returns the correct configured custom error page. I have extended this class to handle exceptions from WebAPI actions by deriving from this class:

默认的ASP.net MVC / WebAPI项目配置了HandleErrorAttribute过滤器,该过滤器处理从操作引发的异常并返回正确配置的自定义错误页面。我已经扩展了这个类,通过从这个类派生来处理来自WebAPI操作的异常:

filters.Add(new HandleExceptionAttribute());

HandleExceptionAttribute

public class HandleExceptionAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
        {
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            filterContext.HttpContext.Response.StatusDescription = filterContext.Exception.Message;
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
        else
        {
            base.OnException(filterContext);
        }
    }
}

This class handles exceptions from WebAPI actions and returns the message of the exception as a JSON response (with the correct HTTP status) to the caller. You might not want to do this if your exception messages aren't user friendly, or if the client doesn't know how to interpret these messages.

此类处理来自WebAPI操作的异常,并将异常消息作为JSON响应(具有正确的HTTP状态)返回给调用者。如果您的异常消息不是用户友好的,或者客户端不知道如何解释这些消息,您可能不希望这样做。

#1


13  

After much reading and experimentation I found this combination of settings to work effectively:

经过大量的阅读和实验,我发现这种设置组合能够有效地发挥作用:

The Friendly Error Pages

One aspx and one html page for each response status code (here's mine):

每个响应状态代码的一个aspx和一个html页面(这是我的):

  • 404.aspx
  • 404.aspx
  • 404.html
  • 404.html
  • 500.aspx
  • 500.aspx
  • 500.html
  • 500.html

The only difference between the two pages is that the aspx pages contain the following lines:

两个页面之间的唯一区别是aspx页面包含以下行:

<% Response.StatusCode = 500 %>
<% Response.TrySkipIisCustomErrors = true %>

The first line sends the correct HTTP status code back to the client, and the second line attempts to persuade IIS that it doesn't need to handle the response itself.

第一行将正确的HTTP状态代码发送回客户端,第二行尝试说服IIS不需要自己处理响应。

Web.config Setup

Custom Errors should be on, or remoteonly, and point to the aspx files:

自定义错误应该打开或远程,并指向aspx文件:

<customErrors mode="On" defaultRedirect="500.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="404.aspx" />
</customErrors>

IIS custom errors should be on too, and point to the html files in the system.webServer section:

IIS自定义错误也应该打开,并指向system.webServer部分中的html文件:

<httpErrors errorMode="Custom" existingResponse="Auto">
  <remove statusCode="404" subStatusCode="-1" />
  <remove statusCode="500" subStatusCode="-1" />
  <error statusCode="404" path="404.html" responseMode="File" />
  <error statusCode="500" path="500.html" responseMode="File" />
</httpErrors>

The existingResponse="Auto" tells IIS to only return the friendly error pages if the SetStatus flag is set. Effectively this allows ASP.net to send back a custom response, its own custom error page from the customErrors section, or allow IIS to return the configured friendly error page.

如果设置了SetStatus标志,则existingResponse =“Auto”告诉IIS仅返回友好错误页面。实际上,这允许ASP.net从customErrors部分发回自定义响应,自己的自定义错误页面,或允许IIS返回配置的友好错误页面。

FilterConfig.cs Setup

A default ASP.net MVC/WebAPI project is configured with a HandleErrorAttribute filter that handles exceptions raised from actions and returns the correct configured custom error page. I have extended this class to handle exceptions from WebAPI actions by deriving from this class:

默认的ASP.net MVC / WebAPI项目配置了HandleErrorAttribute过滤器,该过滤器处理从操作引发的异常并返回正确配置的自定义错误页面。我已经扩展了这个类,通过从这个类派生来处理来自WebAPI操作的异常:

filters.Add(new HandleExceptionAttribute());

HandleExceptionAttribute

public class HandleExceptionAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
        {
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            filterContext.HttpContext.Response.StatusDescription = filterContext.Exception.Message;
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
        else
        {
            base.OnException(filterContext);
        }
    }
}

This class handles exceptions from WebAPI actions and returns the message of the exception as a JSON response (with the correct HTTP status) to the caller. You might not want to do this if your exception messages aren't user friendly, or if the client doesn't know how to interpret these messages.

此类处理来自WebAPI操作的异常,并将异常消息作为JSON响应(具有正确的HTTP状态)返回给调用者。如果您的异常消息不是用户友好的,或者客户端不知道如何解释这些消息,您可能不希望这样做。