Пользовательский 404 ASP.NET возвращает 200 OK вместо 404 Not Found

После попытки настроить мой сайт для инструментов Google для веб-мастеров я обнаружил, что моя пользовательская страница ASP.NET 404 не возвращает код состояния 404. Он отобразил правильную настраиваемую страницу и сообщил браузеру, что все в порядке. Это считается мягким 404 или ложным 404. Google это не нравится. Я нашел много статей по этой проблеме, но решение, которое я хотел, похоже, не сработало.

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

Response.Status = "404 Not Found";
Response.StatusCode = 404;

Это не работает. Страница по-прежнему возвращает 200 OK. Однако я обнаружил, что если я жестко закодирую следующий код в проектный код, он будет работать правильно.

<asp:Content ID = "ContentMain" ContentPlaceHolderID = "ContentPlaceHolderMaster" runat = "server">

<%
    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
%>

 ... Much more code ...

</asp:content>

На странице используется эталонная страница. И я настраиваю пользовательские страницы ошибок в своем web.config. Я бы предпочел использовать вариант кода позади, но я не могу заставить его работать, не вставив встроенный код взлома в дизайн / макет.

Что сообщает браузер? Я использую аддон Header Spy для Firefox.

Bobby Cannon 07.12.2008 09:17

Заголовочный шпионский ответ: HTTP / 1.1 404 Not Found Дата: вс, 7 декабря 2008 г., 06:21:20 по Гринвичу

Ryan Cook 07.12.2008 09:21

Вы используете главную страницу? Может это все. Я попробую страницу без главной страницы ...

Bobby Cannon 07.12.2008 09:23

Нет, я не был, но я тоже могу быстро проверить, я попробую с одним.

Ryan Cook 07.12.2008 09:24

Ага, вот и все! Мастер-страница вызвала 200 OK

Ryan Cook 07.12.2008 09:27

Так что мне нужно разобраться в этой части, интересно, как исправить?

Bobby Cannon 07.12.2008 09:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
80
6
85 338
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Решение:

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

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);
    Response.StatusCode = 404;
}

Чтобы точно определить, когда главная страница устанавливает статус, можно провести дополнительную работу, но я оставлю это вам.


Исходное сообщение:

Мне удалось заставить тестовое веб-приложение работать нормально, ну, по крайней мере, оно отображало настраиваемую страницу с ошибкой и возвращало код состояния 404. Я не могу сказать вам, что не так с вашим приложением, но могу сказать, что я сделал:

1) Отредактировал web.config для пользовательских ошибок:

<customErrors mode = "On">
  <error statusCode = "404" redirect = "404.aspx"/>
</customErrors>

2) Добавил страницу 404.aspx и установил код статуса 404.

public partial class _04 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.StatusCode = 404;
    }
}

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

HTTP/1.1 404 Not Found
Server: Microsoft-IIS/5.1
Date: Sun, 07 Dec 2008 06:04:13 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 533

Теперь, если я перейду на страницу, которая не обрабатывается Asp.Net, например htm-файл, пользовательская страница не отображается и отображается 404, настроенный IIS.

Вот сообщение, в котором приведены некоторые дополнительные сведения, которые могут быть полезны вам и вашей проблеме, мой тест выполняет перенаправление на новую страницу, поэтому URL-адрес запрошенного файла в значительной степени теряется (за исключением его в строке запроса) .

Пользовательские страницы ошибок Google 404 и .NET

Заголовок шпионского ответа:

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
Заголовок шпион - это надстройка Заголовочный шпион для Firefox
Kiquenet 09.09.2015 11:00

Как это работает для статических пользовательских страниц ошибок .html?

ebyrob 27.01.2017 17:48

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

<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>

Это позволит странице вернуть правильный код возврата, несмотря ни на что.

У меня была аналогичная проблема, я хочу показать настраиваемую страницу как 404 (это ASPX), и она отлично работала на localhost, но как только удаленный посетитель подключился, они получали общий IIS 404.

Решением было добавить

Response.TrySkipIisCustomErrors = true;

Перед изменением Response.StatusCode.

Найдено через Rick Strahl http://www.west-wind.com/weblog/posts/745738.aspx

Попробуйте вызвать Response.End (), чтобы пропустить рендеринг ...

Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;

Решение IIS 7 - просто добавить это в ваш файл web.config:

<system.webServer>
  <httpErrors existingResponse = "Replace">
    <remove statusCode = "500" subStatusCode = "-1" />
    <remove statusCode = "404" subStatusCode = "-1" />
    <error statusCode = "404" prefixLanguageFilePath = "" path = "404.htm" responseMode = "File" />
    <error statusCode = "500" prefixLanguageFilePath = "" path = "500.htm" responseMode = "File" />
  </httpErrors>
</system.webServer>

http://forums.asp.net/t/1563128.aspx/1

Сработало у меня! Единственное решение, которое сработало, вероятно, из-за версии, которую вы заметили ... Имейте в виду: вы можете использовать только статические файлы .htm с этим решением.

squarecandy 18.04.2012 23:45

Мне удалось обойти эту проблему, используя следующую настройку в веб-формах asp.net с использованием .NET 3.5.

Реализованный мной шаблон обходит пользовательское решение перенаправления .NET в файле web.config, поскольку я написал свой собственный для обработки всех сценариев с правильным кодом состояния HTTP в заголовке.

Во-первых, раздел customErrors web.config выглядит так:

<customErrors mode = "RemoteOnly" defaultRedirect = "~/error.htm" />

Эта настройка гарантирует, что режим CustomErrors включен, параметр, который нам понадобится позже, и предоставляет параметр all-else-fails для defaultRedirect файла error.htm. Это пригодится, когда у меня нет обработчика для конкретной ошибки или есть что-то вроде разорванного соединения с базой данных.

Во-вторых, вот глобальное событие asax Error:

protected void Application_Error(object sender, EventArgs e)
    {
       HandleError();
    }

    private void HandleError()
    {
        var exception = Server.GetLastError();
        if (exception == null) return;

        var baseException = exception.GetBaseException();

        bool errorHandled = _applicationErrorHandler.HandleError(baseException);
        if (!errorHandled) return;


        var lastError = Server.GetLastError();
    if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
    {
        Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
        Server.ClearError();
    }
    }

Этот код перекладывает ответственность за обработку ошибки на другой класс. Если ошибка не обрабатывается и CustomErrors включен, это означает, что у нас есть случай, когда мы работаем, и почему-то ошибка не была обработана. Мы очистим его здесь, чтобы пользователь не увидел его, но зарегистрируем его в Elmah, чтобы мы знали, что происходит.

Класс applicationErrorHandler выглядит так:

public bool HandleError(Exception exception)
        {
            if (exception == null) return false;

            var baseException = exception.GetBaseException();

            Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);

            if (!HttpContext.Current.IsCustomErrorEnabled) return false;

            try
            {

                var behavior = _responseBehaviorFactory.GetBehavior(exception);
                if (behavior != null)
                {
                    behavior.ExecuteRedirect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }
            return false;
        }

Этот класс по существу использует шаблон команды для поиска подходящего обработчика ошибок для типа выданной ошибки. На этом уровне важно использовать Exception.GetBaseException (), потому что почти каждая ошибка будет заключена в исключение более высокого уровня. Например, выполнение команды «throw new System.Exception ()» с любой страницы aspx приведет к получению исключения HttpUnhandledException на этом уровне, а не System.Exception.

«Заводской» код прост и выглядит так:

public ResponseBehaviorFactory()
    {
        _behaviors = new Dictionary<Type, Func<IResponseBehavior>>
                        {
                            {typeof(StoreException), () => new Found302StoreResponseBehavior()},
                            {typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
                            {typeof(HttpException), () => new HttpExceptionResponseBehavior()},
                            {typeof(Exception), () => new Found302DefaultResponseBehavior()}
                        };
    }

    public IResponseBehavior GetBehavior(Exception exception)
    {                                                                               
        if (exception == null) throw new ArgumentNullException("exception");

        Func<IResponseBehavior> behavior;
        bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);

        //default value here:
        if (!tryGetValue)
            _behaviors.TryGetValue(typeof(Exception), out behavior);

        if (behavior == null)
            Elmah.ErrorSignal.FromCurrentContext().Raise(
                new Exception(
                    "Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
                    exception));
        return behavior();
    }

В конце концов, у меня есть настройка расширяемой схемы обработки ошибок. В каждом определенном «поведении» у меня есть индивидуальная реализация для типа ошибки. Например, исключение Http будет проверяться на предмет кода состояния и обрабатываться соответствующим образом. Для кода состояния 404 потребуется Server.Transfer вместо Request.Redirect, а также соответствующий код состояния, записанный в заголовке.

Надеюсь это поможет.

Вы можете использовать приведенный ниже код:

 Response.TrySkipIisCustomErrors = True
 Response.Status = "404 Not Found"
 Response.AddHeader("Location", "{your-path-to-your-404-page}")

Другие вопросы по теме