Как обойти IIS 7.0 и все-таки вернуть сообщение 404
В своем посте "Как правильно создать страницу 404 или один слуга для двух хозяев"
я писал, что правильная страница "404" должна не только содержать сообщение, понятное пользователю, но и действительно возвращать 404 код ошибки.
Подробно об этом можно почитать в самом сообщении, но если в двух словах, то 404 код ошибки нужен поисковым серверам. Пока поисковики не научились
распознавать текст, им нужно явно указывать, что запрошенной страницы нет. Иначе такие ссылки будут долго болтаться в индексе, а сам сервер будет жаловаться,
что у нескольких страниц вашего сайта не только одинаковые заголовок и мета-теги, но еще и все содержимое.
Все было хорошо до тех пор, пока я случайно не увидел, что происходит на рабочем сервере. В ответ на ошибочный url браузер отобразил
стандартную страницу IIS 7.0 "Page not found".
Полез разбираться. На моем компьютере с Windows Vista и IIS 7.0 все работает отлично - возвращается именно моя страница, прием код возврата - 404.
А вот на рабочем сервере с Windows Server 2008 и IIS 7.0 возвращается стандартная страница IIS.
В результате получается, что сначала ASP.NET приложение корректно обрабатывает 404 ошибку и возвращает ответ браузеру. После чего этот ответ перехватывает
IIS, видит 404 код и заменяет его на на свое стандартное сообщение. Я не скажу точно, было ли это изначально в Windows Server 2008 или, скажем, появилось
вместе с Service Pack 2 - но налицо вот такой неприятный сюрприз. Проявляется он только в IIS Integrated mode, в Classic mode все работает как и раньше.
Кстати, это заставляет задуматься о том, что для качественного тестирования желательно иметь среду, аналогичную production server,
а не Windows 2000 с IIS 6.0 :)
К счастью, решение нашлось благодаря MS MVP Rick Strah
(у него вобще можно найти достаточно много интересных статей по ASP.NET). У Рика были похожие проблемы с кодом 500,
который он хотел возвращать клиентскому сервису. В один прекрасный момент, вместо собщения об ошибке и кода 500
сервис стал получать ... правильно, стандартную страницу IIS "Page not found".
Решить проблему позволило свойство "HttpResponse.TrySkipIisCustomErrors".
Оно появилось в ASP.NET 3.5 и как раз позволяет запретить обработку ошибок IIS 7.0 по умолчанию. Что делать, если ваш сайт работает под .NET 2.0? Сам Рик вежливо пишет,
что в этом случае "you’re out of luck".
В результате, чтобы сформировать правильный ответ, мы можем создать PageNotFound.aspx с необходимым текстом "Вот незадача, бла-бла-бла..." и примерно таким вот кодом:
В последствии, эту страницу можно будет отдавать вызовом
HttpContext ctx = HttpContext.Current; if (ctx == null) throw new NullReferenceException("HttpContext.Current"); ctx.Server.Execute("PageNotFound.aspx", false); ctx.Response.End(); ctx.ApplicationInstance.CompleteRequest();
Вот как-то так. Мне кажется, было бы логичнее, чтобы .NET по умолчанию считал, что TrySkipIisCustomErrors = True, но ... спасибо, что эту проблему можно решить хотя бы так :)