经过大量阅读和实验,我发现这种设置组合可以有效地工作:
友好的错误页面
每个响应状态代码一个 aspx 和一个 html 页面(这是我的):
- 404.aspx
- 404.html
- 500.aspx
- 500.html
两个页面之间的唯一区别是 aspx 页面包含以下行:
<% Response.StatusCode = 500 %>
<% Response.TrySkipIisCustomErrors = true %>
第一行将正确的 HTTP 状态代码发送回客户端,第二行试图说服 IIS 它不需要自己处理响应。
Web.config 设置
自定义错误应该是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"
IIS 仅返回友好错误页面。SetStatus
实际上,这允许 ASP.net 从该customErrors
部分发回自定义响应、它自己的自定义错误页面,或者允许 IIS 返回配置的友好错误页面。
FilterConfig.cs 设置
默认的 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 状态)返回给调用者。如果您的异常消息对用户不友好,或者如果客户端不知道如何解释这些消息,您可能不想这样做。