我有一个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响应共存的正确解决方案是什么?
答案 0 :(得分:13)
经过大量的阅读和实验,我发现这种设置组合能够有效地发挥作用:
每个响应状态代码的一个aspx和一个html页面(这里是我的):
两个页面之间的唯一区别是aspx页面包含以下行:
<% Response.StatusCode = 500 %>
<% Response.TrySkipIisCustomErrors = true %>
第一行将正确的HTTP状态代码发送回客户端,第二行尝试说服IIS,它不需要自己处理响应。
自定义错误应为on
或remoteonly
,并指向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返回配置的友好错误页面。
默认的ASP.net MVC / WebAPI项目配置了HandleErrorAttribute
过滤器,该过滤器处理从操作引发的异常并返回正确配置的自定义错误页面。我已经扩展了这个类,通过从这个类派生来处理WebAPI动作的异常:
filters.Add(new 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状态)返回给调用者。 如果您的例外消息不是用户友好的,或者客户端不知道如何解释这些消息,您可能不想这样做。