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

vot*_*ive 14 asp.net-mvc iis-7 json 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>
Run Code Online (Sandbox Code Playgroud)

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

vot*_*ive 13

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

友好错误页面

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

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

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

<% Response.StatusCode = 500 %>
<% Response.TrySkipIisCustomErrors = true %>
Run Code Online (Sandbox Code Playgroud)

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

Web.config安装程序

自定义错误应该是on,或者remoteonly指向aspx文件:

<customErrors mode="On" defaultRedirect="500.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="404.aspx" />
</customErrors>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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

FilterConfig.cs设置

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

filters.Add(new HandleExceptionAttribute());
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我发现这个答案对我有用,无需创建额外的类或重复的错误页面./sf/ask/1320124781/ (5认同)