IIS7 замінює customErrors під час встановлення Response.StatusCode?


98

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

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

Хтось ще бачив таку поведінку, а також, можливо, знає, як її обійти? Він працював під IIS6, тому я не знаю, чому все змінилося.

Примітка. Це не те саме, що проблема в ASP.NET Custom 404 Повернення 200 ОК замість 404 Не знайдено


У мене було те саме питання. Тут уже відповіли http://stackoverflow.com/questions/347281/asp-net-custom-404-returning-200-ok-instead-of-404-not-found .
Боббі Кеннон

Боббі, я насправді знайшов це питання і спробував його, але це не вирішило проблему. Але спасибі
Микола

Я хотів би прокоментувати, що ця проблема також виникає при переході від Classic до інтегрованого трубопроводу Я використовував рішення @PavelChuchuva (також працює @RickStrahl). Я здогадуюсь, що "перехід" у Classic є автоматичним, в "Інтегрованому" це сприймає глобальну обробку сторінки сервера з помилками ..
sonjz

Відповіді:


116

Встановіть існуючийResponse на PassThrough в розділі system.webServer / httpErrors:

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

Значенням за замовчуванням існуючої властивостіResponse є Авто:

Авто повідомляє користувальницький модуль помилок робити правильно . На фактичний текст помилки, який бачать клієнти, впливатиме залежно від значення fTrySkipCustomErrors, що повертається під час IHttpResponse::GetStatusвиклику. Коли для fTrySkipCustomErrors встановлено значення true, користувацький модуль помилок дозволить пройти відповідь, але якщо встановлено значення false, користувацький модуль помилок замінює текст власним текстом.

Додаткова інформація: Чого очікувати від користувацького модуля помилок IIS7


3
Зауважте, що встановлення існуючогоResponse на PassThrough може призвести до деяких побічних ефектів. Будь ласка, переконайте посилання, надане Павлом перед будь-якими змінами.
Lex Li

Є <httpErrors existingResponse="PassThrough" />рівнозначним Response.TrySkipIisCustomErrorsчи вони поводяться по-різному?
Asbjørn Ulsberg

1
@sbjornu Вони досягають того ж самого, але з Response.TrySkipIisCustomErrorsвами краще контролювати, коли відображати користувацькі помилки IIS.
Павло Чучува

дякую, я бачив багато інформації про response.tryskipiiscustomerrors, але не стільки про існуючі відповіді.
HBCondo

Я вирішив проблему із тим, що користувальницькі сторінки помилок не працюють на моєму веб-хості під керуванням IIS7, просто встановивши наявнийResponse = "Автоматичний", що було дуже дивно, оскільки ця стаття стверджує, що це за замовчуванням. Очевидно, це не так ... або моя хостингова компанія встановила неправильний дефолт в іншому місці, я думаю. Так чи інакше, я сподіваюся, що це заощадить когось на кілька годин: \
Ерік Сассаман

80

Найпростіший спосіб зробити поведінку послідовним - це очистити помилку та використовувати Response.TrySkipIisCustomErrors та встановити її на true. Це скасує обробку сторінки глобальної помилки IIS з вашої сторінки або глобального обробника помилок у Application_Error.

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

Як правило, ви повинні це зробити у вашому оброблювальному пристрої Application_Error, який обробляє всі помилки, які обробники помилок вашої програми не отримують.

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


2
Це також не працює для мене (IIS8), і поради, схоже, не відповідають ОП (якщо я читаю правильно). Я хочу, щоб customErrorналаштований у Web.config спрацьовував. З Response.TrySkipIisCustomErrors = trueмоєю поведінкою я маю таку саму поведінку: відображається потворна сторінка помилок, створена сервером. З ним встановлено, що falseнічого не відбувається - порожнє вікно браузера.
Шон Південь,

Добре працював для мене! Хоча обстановка, яку Павло Чучува згадує у своїй відповіді, також працювала, це мало деякі побічні ефекти, які спричинили інші проблеми. Цей параметр дозволив мені пропустити помилку IIS за допомогою конкретного сценарію, який я хотів, залишаючи поведінку недоторканою для всього іншого.
Кевін Тіге

Добре працював у Azure для мене. Заголовки сервераServer:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET
oxfn

Я все ще вважаю, що мені потрібно налаштувати, customErrors mode="Off"щоб це працювало. Якщо я це роблю, тоді httpErrors postojeResponse = "Авто" (за замовчуванням) працює для мене належним чином, коли я використовую код у цій відповіді.
AaronLS

11

Вирішено: виявляється, що "Детальні помилки" потрібно вмикати, щоб IIS7 "пройшов" будь-яку сторінку помилок. Дивіться http://forums.iis.net/t/1146653.aspx


1
Хоча ця і була позначена як відповідь, я вважаю, що варто прочитати інші відповіді, щоб отримати більше розумінь з цієї теми.
Lex Li

Також його можна було б добре зняти. HandleErrorAttribute у FilterConfig
за G

4

Я не впевнений, схожий він за своєю суттю чи ні, але я вирішив питання, яке на поверхні схоже, і ось, як я це впорався.

Перш за все, значення для замовчування для існуючихResponse (Авто) було правильною відповіддю в моєму випадку, оскільки у мене є власні 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, якщо він насправді не є мертвою сторінкою.

У всякому разі, саме так я і зробив. Сподіваюся, що хтось допомагає.


3

Це питання стало головним болем. Жодна з вищезазначених пропозицій не вирішила це для мене, тому я включаю своє рішення. Для запису наше середовище / платформа використовує:

  • .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");

Тоді я повинен був Configure як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.

PS За допомогою цих налаштувань мені не потрібно було встановлювати Response.TrySkipIisCustomErrors


2

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, тому є деякий простір для поліпшення цього коду.


0

За замовчуванням IIS 7 використовує детальні спеціальні повідомлення про помилки, тому я вважаю, що Response.StatusCode дорівнюватиме 404.XX, а не лише 404.

Ви можете налаштувати IIS7, щоб використовувати простіші коди повідомлень про помилки або змінити свій код, обробляючи більш детальні повідомлення про помилки, які пропонує IIS7.

Більше інформації можна отримати тут: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

Подальше розслідування показало, що у мене це неправильно - детальні повідомлення не за замовчуванням, але, можливо, вони увімкнено у вашому полі, якщо ви бачите різні повідомлення про помилки, які ви згадали.


Response.StatusCode - ціле число, тому я не бачу способу встановлення більш конкретного коду, ніж просто "404". У мене налаштовано IIS7 для використання / показу користувацьких сторінок помилок, як указує ваша URL-адреса.
Микола

Гммм ... На жаль, на даний момент я не можу перевірити, оскільки я не вдома. Якщо до цього часу у вас немає рішення - я сьогодні загляну.
nullnvoid
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.