Я весь день пытался реализовать обработку ошибок в моем приложении ASP.NET MVC 2. Я изучил множество техник, но ни одна из них не работает должным образом. Я использую MVC2 и .NET 4.0 (начал проект до того, как был выпущен MVC3; мы обновим его после того, как поставим наш первоначальный выпуск).
На этом этапе я буду счастлив правильно обработать ошибки 404 и 500 - тоже подойдет ошибка 403 (требуется авторизация), за которой последуют различные другие конкретные ответы. Прямо сейчас я получаю либо все 404, либо все 500, либо все 302 до 404, либо все 302 до 500.
Вот мои требования (которые должны быть довольно близки к основным требованиям HTTP):
Если ресурс не найден, вывести 404 и отобразить страницу, относящуюся к 404, с запрошенным URL. НЕ возвращайте промежуточный код ответа, например 302. В идеале, сохраните запрошенный URL, а не показывайте новый URL, например
/Error/NotFound
, но если последний отображается, убедитесь, что мы не вернули ответ перенаправления, чтобы получить его.Если произошла внутренняя ошибка сервера, выведите 500 и отобразите ошибку 500 с некоторым указанием того, что пошло не так. Опять же, не возвращайте промежуточный код ответа и, в идеале, не меняйте URL-адрес.
Вот что я бы назвал 404:
- Статический файл не найден:
/Content/non-existent-dir/non-existent-file.txt
- Контроллер не найден:
/non-existent-controller/Foo/666
- Контроллер найден, но действие не найдено:
/Home/non-existent-action/666
- Контроллер и действие найдены, но действие не может найти запрошенный объект:
/Home/Login/non-existent-id
Вот что я бы назвал 500:
- Опубликовать неверное значение:
POST /User/New/new-user-name-too-long-for-db-column-constraint
- Проблема, не связанная с данными, например, не отвечает конечная точка веб-службы.
Некоторые из этих проблем необходимо идентифицировать с помощью конкретных контроллеров или моделей, а затем контроллеры должны генерировать соответствующее исключение HttpException. С остальным следует обращаться более обобщенно.
Для случая 404 № 2 я попытался использовать настраиваемый ControllerFactory для выдачи 404, если контроллер не может быть найден. Для случая №3 404 я попытался использовать настраиваемый базовый контроллер, чтобы переопределить HandleUnknownAction
и выдать ошибку 404.
В обоих случаях я получаю 302 перед 404. И я никогда не получаю 500 ошибок; если я изменю Web.config, чтобы вставить опечатку в конечную точку моей веб-службы, я все равно получу 302, затем 404, в котором указывается, что URL-адрес (контроллер / действие), который использует, веб-служба не может быть найдена . Я также получаю запрошенный URL как (n нежелательных) параметров строки запроса: /Error/NotFound?aspxerrorpath=/Home/non-existent-action
Оба эти метода пришли из http://www.niksmit.com/wp/?p=17 (Как получить обычные страницы с ошибкой 404 (Страница не найдена) с помощью ASP.Net MVC), на которую указывает http://richarddingwall.name/2008/08/17/strategies-for-наосновересурсов-404-ошибок-в-aspnet-mvc/
Если в Web.config у меня есть <customErrors mode="On" defaultRedirect="~/Error/Unknown" redirectMode="ResponseRedirect" />
, я получаю соответствующий код ответа, но мой контроллер ошибок никогда не вызывается. Удаление атрибута redirectMode
дает мне представление об ошибках MVC, но с промежуточным 302 и измененным URL - и всегда с тем же контроллером (Unknown
= 500; если я изменю его на NotFound
, все будет выглядеть как 404).
Вот еще кое-что, что я прочитал и попытался реализовать:
- http://www.davidjuth.com/asp-net-mvc-error-handler.aspx
- http://sanjayuttam.com/wordpress/index.php/c-sharp/c-sharp-code-examples/error-handling-in-asp-net-mvc-1-part-2-of-2/
- http://blog.hebbink.com/post/2010/12/14/NET-custom-404-error-page-returns-302-for-http-status.aspx
- http://blog.dantup.com/2009/04/aspnet-mvc-handleerror-attribute-custom.html
- http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx
.. вместе с кучей сообщений StackOverflow.
Мне кажется, такая обработка ошибок довольно проста для веб-приложений, и у инфраструктуры MVC должны быть настройки по умолчанию, которые делают это из коробки и позволяют людям расширять ее для работы в противном случае. Возможно, они сделают это в будущем выпуске. А пока кто-нибудь может дать мне исчерпывающие сведения о том, как реализовать правильные HTTP-ответы?