IIS7 переопределяет customErrors при установке Response.StatusCode?

Здесь странная проблема. Всем известно, что если вы используете раздел customErrors в web.config для создания настраиваемой страницы ошибок, вы должны установить свой Response.StatusCode на то, что вам подходит. Например, если я создам настраиваемую страницу 404 и назову ее 404.aspx, я могу поместить <% Response.StatusCode = 404 %> в содержимое, чтобы у нее был настоящий заголовок статуса 404.

Следуй за мной так далеко? Хорошо. Теперь попробуйте сделать это на IIS7. Я не могу заставить его работать, и точка. Если Response.StatusCode установлен на настраиваемой странице ошибки, IIS7, кажется, полностью переопределяет настраиваемую страницу ошибки и показывает свою собственную страницу состояния (если она у вас настроена).

Кто-нибудь еще видел такое поведение и, возможно, знает, как его обойти? Он работал под IIS6, поэтому я не знаю, почему все изменилось.

Примечание. Это не то же самое, что проблема в Пользовательский 404 ASP.NET Возвращает 200 ОК вместо 404 Не найдено


person Nicholas    schedule 12.01.2009    source источник
comment
У меня такой же вопрос. Здесь уже ответил http://stackoverflow.com/questions/347281/asp-net-custom-404-returning-200-ok-instead-of-404-not-found.   -  person Bobby Cannon    schedule 12.01.2009
comment
Бобби, я действительно нашел этот вопрос и попробовал, но это не помогло. Но спасибо.   -  person Nicholas    schedule 12.01.2009
comment
Я хотел бы отметить, что эта проблема также возникает при переходе с классической системы на интегрированную. Я использовал решение @PavelChuchuva (решение @RickStrahl тоже работает). Я предполагаю, что переход в Classic выполняется автоматически, а в Integrated требуется глобальная обработка страницы ошибок сервера.   -  person sonjz    schedule 16.01.2015


Ответы (7)


В разделе system.webServer / httpErrors укажите для existingResponse значение PassThrough:

  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

Значение по умолчанию для свойства existingResponse - Auto:

Авто сообщает настраиваемому модулю ошибок, что нужно делать правильные действия. Фактический текст ошибки, видимый клиентами, будет изменен в зависимости от значения fTrySkipCustomErrors, возвращаемого в вызове IHttpResponse::GetStatus. Когда для fTrySkipCustomErrors установлено значение true, пользовательский модуль ошибок пропускает ответ, но если для него установлено значение false, пользовательский модуль ошибок заменяет текст собственным текстом.

Дополнительная информация: Чего ожидать от пользовательского модуля ошибок IIS7

person Pavel Chuchuva    schedule 31.03.2009
comment
Обратите внимание, что установка параметра existingResponse на PassThrough может привести к некоторым побочным эффектам. Пожалуйста, усвойте ссылку, предоставленную Павлом, перед любыми изменениями. - person Lex Li; 12.02.2010
comment
<httpErrors existingResponse="PassThrough" /> эквивалентно Response.TrySkipIisCustomErrors или они ведут себя по-другому? - person Asbjørn Ulsberg; 30.06.2011
comment
@sbjornu Они достигают того же, но с Response.TrySkipIisCustomErrors вы лучше контролируете, когда отображать пользовательские ошибки IIS. - person Pavel Chuchuva; 04.07.2011
comment
спасибо, я видел много информации о response.tryskipiiscustomerrors, но не столько о существующем ответе. - person HBCondo; 23.02.2012
comment
Я решил проблему с настраиваемыми страницами ошибок, которые не работают на моем веб-узле, на котором запущен IIS7, просто установив existingResponse = Auto, что было очень удивительно, поскольку в упомянутой статье утверждается, что это значение по умолчанию. Очевидно, это не так ... или я полагаю, что моя хостинговая компания установила неправильное значение по умолчанию в другом месте. В любом случае, я надеюсь, что это сэкономит кому-то несколько часов: \ - person Eric Sassaman; 29.04.2013
comment
Хотя у нас был HttpContext.Current.Response.TrySkipIisCustomErrors = true; но это не сработало. Но после этого моя проблема была решена. - person Abhishek Shrivastava; 06.06.2014

Самый простой способ сделать поведение согласованным - сбросить ошибку и использовать Response.TrySkipIisCustomErrors и установите для него значение true. Это переопределит обработку страницы глобальной ошибки IIS изнутри вашей страницы или глобальный обработчик ошибок в Application_Error.

Server.ClearError();
Response.TrySkipIisCustomErrors = true;

Обычно это следует делать в обработчике Application_Error, который обрабатывает все ошибки, которые обработчики ошибок вашего приложения не улавливают.

Более подробную информацию можно найти в этом сообщении блога: http://www.west-wind.com/weblog/posts/745738.aspx

person Rick Strahl    schedule 01.05.2009
comment
Это также не работает для меня (IIS8), и совет, похоже, не соответствует OP (при условии, что я правильно его читаю). Я хочу, чтобы активировался customError, настроенный в Web.config. С Response.TrySkipIisCustomErrors = true я получаю такое же поведение: отображается уродливая страница ошибки, созданной сервером. Если для него установлено значение false, ничего не происходит - пустое окно браузера. - person Shawn South; 26.02.2014
comment
У меня отлично заработало! Хотя настройка, о которой Павел Чучува упоминает в своем ответе, также работала, у нее были некоторые побочные эффекты, которые вызвали другие проблемы. Этот параметр позволил мне пропустить переопределение ошибки IIS в конкретном сценарии, который я хотел, оставив при этом поведение для всего остального. - person Kevin Tighe; 06.05.2015
comment
Хорошо работал у меня в Azure. Заголовки сервера Server:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET - person oxfn; 05.10.2015
comment
Я все еще считаю, что мне нужно установить customErrors mode="Off", чтобы это работало. Если я это сделаю, тогда httpErrors existingResponse = Auto (по умолчанию) будет работать у меня правильно, когда я использую код в этом ответе. - person AaronLS; 17.06.2019

Решено: выяснилось, что «Подробная информация об ошибках» должна быть включена, чтобы IIS7 мог «передавать» любую страницу с ошибкой, которая у вас может быть. См. http://forums.iis.net/t/1146653.aspx

person Nicholas    schedule 12.01.2009
comment
Хотя этот был отмечен как ответ, я думаю, что стоит потратить время, чтобы прочитать другие ответы, чтобы получить больше информации по теме. - person Lex Li; 12.02.2010
comment
Также можно было бы удалить. Атрибут HandleErrorAttribute в FilterConfig - person Per G; 26.06.2013

Я не уверен, похоже это по природе или нет, но я решил проблему, которая на первый взгляд кажется похожей, и вот как я с этим справился.

Прежде всего, значение по умолчанию для existingResponse (Auto) было правильным ответом в моем случае, поскольку у меня есть собственные 404, 400 и 500 (я мог бы создать другие, но этих трех будет достаточно для того, что я делаю). Вот соответствующие разделы, которые мне помогли.

Из web.config:

<customErrors mode="Off" />

И

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/errors/404.aspx" responseMode="ExecuteURL" />
  <error statusCode="500" path="/errors/500.aspx" responseMode="ExecuteURL" />
  <error statusCode="400" path="/errors/400.aspx" responseMode="ExecuteURL" />
</httpErrors>

Оттуда я добавил это в Application_Error на global.asax:

    Response.TrySkipIisCustomErrors = True

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

Во всяком случае, вот как я это сделал. Надеюсь, это кому-то поможет.

person SEFL    schedule 31.07.2013

Эта проблема была большой головной болью. Ни одно из ранее упомянутых предложений само по себе не решило эту проблему, поэтому я включаю свое решение. Для справки, наша среда / платформа использует:

  • .NET Framework 4
  • MVC 3
  • IIS8 (рабочая станция) и IIS7 (веб-сервер)

В частности, я пытался получить ответ HTTP 404, который перенаправлял бы пользователя на нашу настраиваемую страницу 404 (через настройки Web.config).

Во-первых, мой код должен был выдать HttpException. Возврат NotFoundResult от контроллера не дал тех результатов, к которым я стремился.

throw new HttpException(404, "There is no class with that subject");

Затем мне пришлось настроить оба узла customErrors и httpError в Web.config.

<customErrors mode="On" defaultRedirect="/classes/Error.aspx">
  <error statusCode="404" redirect="/classes/404.html" />
</customErrors>

...

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/classes/404.aspx" responseMode="ExecuteURL" />
</httpErrors>

Обратите внимание, что я оставил existingResponse как Auto, что отличается от решения, предоставленного @sefl.

Параметры customErrors оказались необходимыми для обработки моего явно брошенного HttpException, в то время как узел httpErrors обрабатывал URL-адреса, которые выходили за рамки шаблонов маршрутов, указанных в Globals.asax.cs.

P.S. С этими настройками мне не нужно было устанавливать Response.TrySkipIisCustomErrors

person Shawn South    schedule 26.02.2014

TrySkipIisCustomErrors - это только часть головоломки. Если вы используете настраиваемые страницы ошибок, но также хотите доставлять некоторый контент RESTful на основе статусов 4xx, у вас есть проблема. Установка httpErrors.existingResponse web.config на «Авто» не работает, потому что .net, кажется, всегда доставляет некоторое содержимое страницы в IIS, поэтому использование «Авто» приводит к тому, что все (или, по крайней мере, некоторые) пользовательские страницы ошибок не используются. Использование «Заменить» тоже не сработает, потому что ответ будет содержать ваш код статуса http, но его содержимое будет пустым или заполнено страницей с настраиваемой ошибкой. А «PassThrough» фактически отключает CEP, поэтому его нельзя использовать.

Поэтому, если вы хотите обойти CEP в некоторых случаях (под обходом я имею в виду возврат статуса 4xx с некоторым содержанием), вам понадобится дополнительный шаг: очистите ошибку:

void Application_Error(object sender, EventArgs e)
{
    var httpException = Context.Server.GetLastError() as HttpException;
    var statusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;

    Context.Server.ClearError();
    Context.Response.StatusCode = statusCode;
}

Поэтому, если вы хотите использовать ответ REST (например, 400 - неверный запрос) и отправить с ним некоторый контент, вам просто нужно будет установить TrySkipIisCustomErrors где-нибудь в действии и установить existingResponse на «Авто» в разделе httpErrors в web.config. В настоящее время:

  • когда нет ошибки (действие возвращает 4xx или 5xx) и возвращается некоторый контент, CEP не используется, и контент передается клиенту;
  • когда возникает ошибка (создается исключение), содержимое, возвращаемое обработчиками ошибок, удаляется, поэтому используется CEP.

Если вы хотите вернуть статус с пустым содержимым из вашего действия, он будет рассматриваться как пустой ответ и будет показан CEP, поэтому есть место для улучшения этого кода.

person Łukasƨ Fronczyk    schedule 27.12.2017

По умолчанию IIS 7 использует подробные настраиваемые сообщения об ошибках, поэтому я предполагаю, что Response.StatusCode будет равно 404.XX, а не просто 404.

Вы можете настроить IIS7 для использования более простых кодов сообщений об ошибках или изменить свой код, обрабатывающий более подробные сообщения об ошибках, которые предлагает IIS7.

Дополнительная информация доступна здесь: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enables-custom-error-pages.aspx

Дальнейшее расследование показало, что у меня все было не так - подробных сообщений нет по умолчанию, но, возможно, они были включены в вашем ящике, если вы видите разные сообщения об ошибках, которые вы упомянули.

person nullnvoid    schedule 12.01.2009
comment
Response.StatusCode - целое число, поэтому я не вижу способа установить более конкретный код, чем просто 404. У меня IIS7 настроен на использование / отображение пользовательских страниц ошибок, как указывает ваш URL-адрес. - person Nicholas; 12.01.2009
comment
Хммм ... К сожалению, в настоящий момент я не могу протестировать, так как я не на своем домашнем компьютере. Если к тому времени у вас не будет решения - посмотрю сегодня вечером. - person nullnvoid; 12.01.2009