Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
С помощью двух секций customErrors и httpErrors в файле конфигурации мы можем задать в ASP.NET MVC 5 обработку статусных кодов ошибок.
Секция customErrors в web.config позволяет задать собственные страницы ошибок для различных статусных кодов HTTP. Правда, применение этой секции имеет ограничения.
Вначале добавим в проект свои страницы ошибок. Например, для обработки ошибки 404 добавим в корень проекта файл 404.html:
<!DOCTYPE html> <html> <head> <title>Ошибка 404</title> <meta charset="utf-8" /> </head> <body> <h2>Ошибка 404. Ресурс не найден</h2> </body> </html>
Подобным образом добавим файлы и для других ошибок.
Далее найдем в файле конфигурации web.config секцию system.web и поместим в нее подсекцию
customErrors
(если эта подсекция уже есть, изменим ее):
<system.web> <compilation debug="true" targetFramework="4.6" /> <httpRuntime targetFramework="4.6" /> <customErrors mode="On"> <error statusCode="404" redirect="~/404.html"/> <error statusCode="403" redirect="~/403.html"/> </customErrors> </system.web>
Внутри секции customErrors
помещаются элементы error
, каждый из которых задает код ошибки (атрибут statusCode
)
и страницу переадресации при ошибке (атрибут redirect
)
Если мы сейчас запустим приложение и обратимся к несуществующему ресурсу, то нам отобразится наша страница с ошибкой:
Однако при такой переадресации мы сталкиваемся с рядом проблем. Во-первых, в качестве адреса используется не оригинальный путь, к которому идет обращение, а 404.html. То есть вместо строки запроса /Home/Some, мы получаем /404.html?aspxerrorpath=/Home/Some. Во-вторых, при отдаче ответа клиент получает статусный код 200, то есть запрос успешно обработан, вместо кода 404.
Чтобы решить первую проблему, добавим к определению секции атрибут redirectMode="ResponseRewrite"
:
<customErrors mode="On" redirectMode="ResponseRewrite"> <error statusCode="404" redirect="~/404.html"/> <error statusCode="403" redirect="~/403.html"/> </customErrors>
Теперь страницу с ошибкой можно будет увидеть напрямую по запрошенному пути. Однако клиенту все равно будут отдаваться статусный код 200.
Более того у нас есть еще и другая проблема. Если мы напрямую возвратим из метода контроллера статусный код ошибки, то этот код никак не будет обрабатываться, и настройки в customErrors на него не подействуют. Например:
public class HomeController : Controller { public ActionResult Index() { return HttpNotFound(); } }
При обращении к нему мы получим стандартное сообщение об ошибке:
И для решения возникших проблем нам надо использовать не customErrors
, а элемент httpErrors.
Вначале для обработки ошибок добавим в приложение новый контроллер ErrorController:
public class ErrorController : Controller { public ActionResult NotFound() { Response.StatusCode = 404; return View(); } public ActionResult Forbidden() { Response.StatusCode = 403; return View(); } }
Добавим представление для метода NotFound:
@{ ViewBag.Title = "Ошибка 404"; } <h2>Ошибка 404. Ресурс не найден</h2>
Подобным образом добавим представление и для других методов.
Далее добавим элемент httpErrors
. Этот элемент помещается внутрь секции system.webServer. Если
этой секции внутри web.config нет, то ее можно добавить. А узел customErrors
мы можем удалить или закомментировать:
<system.web> <compilation debug="true" targetFramework="4.6" /> <httpRuntime targetFramework="4.6" /> <!--<customErrors mode="On" redirectMode="ResponseRewrite"> <error statusCode="404" redirect="~/Error/NotFound"/> <error statusCode="403" redirect="~/Error/Forbidden"/> </customErrors>--> </system.web> <system.webServer> <httpErrors errorMode="Custom" existingResponse="Replace"> <clear/> <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL"/> <error statusCode="403" path="/Error/Forbidden" responseMode="ExecuteURL"/> </httpErrors> </system.webServer>
Элемент httpErrors имеет ряд настроек. Чтобы протестировать настройки локально, устанавливается атрибут errorMode="Custom"
.
Если тестирование необязательно, и приложение уже развернуто для использования, то можно установить значение errorMode="DetailedLocalOnly"
.
Значение existingResponse="Replace"
позволит отобразить ошибку по оригинальному запрошенному пути без переадресации.
Внутри элемента httpErrors с помощью отдельных элементов error устанавливается обработка ошибок. Атрибут statusCode
задает статусный код, атрибут path
- адрес url, который будет вызываться, а атрибут responseMode
указывает, как будет обрабатываться ответ вызванному url.
Атрибут responseMode
может принимать три значения:
ExecuteURL
: производит рендеринг ответа полученного при вызове адреса url из атрибута path
Redirect
: выполняет переадресацию со статусным кодом 302
File
: рассматривает адрес url из атрибута path как статическую страницу и использует ее в качестве ответа
Настройки элемента httpErrors
могут наследоваться с других уровней, например, от файла конфигурации machine.config
. И чтобы удалить
все унаследованные настройки, применяется элемент <clear />
. Чтобы удалить настройки для отдельных ошибок, применяется элемент
<remove />
:
<httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404"/> <remove statusCode="403"/> <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL"/> <error statusCode="403" path="/Error/Forbidden" responseMode="ExecuteURL"/> </httpErrors>
И теперь, если мы запустим приложение и обратимся по несуществующему пути или к методу, который возвращает статусный код 404, то у нас отобразится ответ от метода NotFound контроллера ErrorController:
Установка атрибута responseMode="File"
позволяет использовать в качестве ответа статические файлы. Например, используем ранее определенные файлы ошибок:
<httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404"/> <remove statusCode="403"/> <error statusCode="404" path="404.html" responseMode="File"/> <error statusCode="403" path="403.html" responseMode="File"/> </httpErrors>