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

时间:2014-05-21 10:04:08

标签: asp.net-mvc json iis-7 asp.net-web-api asp.net-identity-2

我有一个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>

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

1 个答案:

答案 0 :(得分:13)

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

友好错误页面

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

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

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

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

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

Web.config Setup

自定义错误应为onremoteonly,并指向aspx文件:

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

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>

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

FilterConfig.cs设置

默认的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);
        }
    }
}

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