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