Отправляет email-рассылки с помощью сервиса Sendsay

.NET: Записки программиста

  Все выпуски  

Как обойти IIS 7.0 и все-таки вернуть сообщение 404


Рассылка сайта .NET: Записки программиста Сайт .NET: Записки программиста

Как обойти IIS 7.0 и все-таки вернуть сообщение 404

IIS 7.0 404 В своем посте "Как правильно создать страницу 404 или один слуга для двух хозяев" я писал, что правильная страница "404" должна не только содержать сообщение, понятное пользователю, но и действительно возвращать 404 код ошибки. Подробно об этом можно почитать в самом сообщении, но если в двух словах, то 404 код ошибки нужен поисковым серверам. Пока поисковики не научились распознавать текст, им нужно явно указывать, что запрошенной страницы нет. Иначе такие ссылки будут долго болтаться в индексе, а сам сервер будет жаловаться, что у нескольких страниц вашего сайта не только одинаковые заголовок и мета-теги, но еще и все содержимое.

Все было хорошо до тех пор, пока я случайно не увидел, что происходит на рабочем сервере. В ответ на ошибочный url браузер отобразил стандартную страницу IIS 7.0 "Page not found". 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 с необходимым текстом "Вот незадача, бла-бла-бла..." и примерно таким вот кодом:

protected override void OnLoad(EventArgs e)
{
  base.OnLoad(e);

  Response.StatusCode = (Int32)HttpStatusCode.NotFound;
  Response.TrySkipIisCustomErrors = true;    //  Иначе IIS 7.0 возвращает стандартную 404 страницу
}

В последствии, эту страницу можно будет отдавать вызовом

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, но ... спасибо, что эту проблему можно решить хотя бы так :)



блог сайта .NET: Записки программиста Подпишись на блог сайта .NET: Записки программиста

В избранное