Ответ 1
После долгих чтений и экспериментов я нашел, что эта комбинация настроек работает эффективно:
Дружественные страницы ошибок
Один 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 также должны быть включены и указывать на html файлы в разделе system.webServer
:
<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());
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) вызывающему. Возможно, вы не захотите сделать это, если ваши сообщения об исключениях не являются дружественными пользователю или если клиент не знает, как интерпретировать эти сообщения.