Как отправить код состояния «500» на страницу общей ошибки в IIS?

Я использую общую страницу ошибок с использованием директивы ASP.NET .

<customErrors mode="On" defaultRedirect="500.html" redirectMode="ResponseRewrite">
</customErrors>

Проблема - при возникновении ошибки эта страница не возвращает статус HTTP "500". Он равен 200. Таким образом, средства проверки ссылок и пауки не видят каких-либо проблем.

Как я могу отправить статус HTTP 500 вместе со статической страницей 500.html?

Требования:

  • Я должен использовать redirectMode = "ResponseRewrite"
  • Я не могу использовать динамическую страницу, только статический .html.
10
задан pnuts 19 November 2015 в 01:37
поделиться

6 ответов

В документации MSDN для элемента customErrors указано, что он реализован System.Web.Configuration.CustomErrorsSection. Если мы используем Red Gate .NET Reflector для анализа этого класса, мы можем увидеть, где этот параметр используется в Framework.

Используется System.Web.UI.Page.HandleError и System.Web.HttpResponse.ReportRuntimeError.

Оба они в конечном итоге вызывают System.Web.HttpResponse.RedirectToErrorPage. (Название этого метода сбивает с толку: важно отметить, что RedirectToErrorPage принимает параметр redirectMode в качестве параметра, поэтому он вызывается, даже если вы используете ResponseRewrite и на самом деле перенаправление не происходит.)

Соответствующая часть RedirectToErrorPage Метод таков:

    if (redirectMode == CustomErrorsRedirectMode.ResponseRewrite)
    {
        this.Context.Server.Execute(url);
    }

Похоже, нет никакого способа установить код ответа в обработке ошибок: в конце концов, это просто Server.Execute. Поэтому кажется неизбежным, что вам нужно будет написать код для получения желаемого HTTP-ответа.

Можете ли вы пересмотреть, почему вы хотите использовать простой файл .html? Это кажется разумным выбором для обработки ошибок, потому что вы не хотите проходить через все накладные расходы страницы .aspx, когда это может привести к возникновению другой ошибки.

Но, возможно, есть какая-то золотая середина, которая будет такой же надежной, как файл .html?

Например, вы можете создать предварительно скомпилированный HttpHandler, зарегистрировав его по URL-адресу /500.error, а затем сделайте 500.error страницей перенаправления по умолчанию. (Это будет похоже на то, как работает ScriptResource.axd.) Если вы предварительно скомпилируете свой модуль в DLL (в отличие от компиляции на лету из простого старого файла .axd), вы можете обнаружить, что он так же надежен в состояние ошибки. Если вы столкнулись с ошибкой, при которой даже это не сработает, то статический файл .html, вероятно, тоже не сработает — имейте в виду, что директива customErrors по-прежнему полагается на .NET, работающий под капотом, и по-прежнему использует StaticFileHandler для обслуживания ваш .html файл.

В качестве альтернативы вы можете рассмотреть возможность использования обратного прокси-сервера перед вашим приложением IIS, который будет обслуживать дружественные 500 страниц даже в случае катастрофического сбоя пула приложений. Это потребовало бы больше работы для настройки, но было бы даже более надежным, чем customErrors, например. если ваш web.config будет поврежден, даже customErrors не будут работать.

7
ответ дан 3 December 2019 в 23:10
поделиться

Попробуйте настроить раздел пользовательских ошибок следующим образом:

<customErrors mode="On" redirectMode="ResponseRewrite">
  <error statusCode="500" redirect="500.aspx">
</customErrors>

В файле 500.aspx измените код ответа в page_load;

Response.StatusCode = 500;
Response.StatusDescription = "Internal Server Error";
1
ответ дан 3 December 2019 в 23:10
поделиться

В файл gllobal.asax добавьте следующий код

protected void Application_EndRequest(object sender, EventArgs e)
    {
        if (Request.Url.AbsolutePath.EndsWith("500.html"))
            Response.StatusCode = 500;
    }
4
ответ дан 3 December 2019 в 23:10
поделиться

Если вы настаиваете на изменении базовой HTTP-сигнализации, вам придется либо уступить некоторым требованиям, либо подготовиться к написанию собственного веб-сервера. Да, вам нужно запустить интегрированный в IIS7 AppPool, и вам все равно, возможно, придется принять перенаправление на активную страницу, поскольку вы пытаетесь имитировать, что ваш сервер не работает, а сервер не предназначен для имитации самоубийства. Так что, если это дает вам один простой способ сделать это, вы можете либо сказать спасибо, либо разработать свой собственный, несовместимый с HTTP сервер, который будет шифровать коды ответов по желанию.

-1
ответ дан 3 December 2019 в 23:10
поделиться

Хорошо, у меня есть решение, единственный способ заставить его работать – обойти раздел пользовательских ошибок в файле веб-конфигурации.

Итак, пример default.aspx

public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        throw new Exception("boom");
    }
}

Затем в файле global.asax:

protected void Application_Error(object sender, EventArgs e)
{
    // Clear the error to take control of process
    Server.ClearError();

    Response.WriteFile(Server.MapPath("500.html"));
    Response.StatusCode = 500;
    Response.StatusDescription = "Internal Server Error";
}

Вы, вероятно, можете написать лучший механизм обработки для части 500.html — я думаю, что это должно делать то, что вы пытаетесь достичь .

Проверено только с веб-сервером VS Cassini, однако я не вижу причин, по которым это не должно работать в iis6.

3
ответ дан 3 December 2019 в 23:10
поделиться

Это можно сделать с помощью фильтра isapi. Это должно быть написано на c, но оно может изменить статус ответа для запроса .html, чтобы браузер получил 500 с вашей пользовательской html-страницей.

0
ответ дан 3 December 2019 в 23:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: