Вопрос

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

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

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

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

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

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

 ... Much more code ...

</asp:content>

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

Это было полезно?

Решение

Решение:

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

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

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

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

Решением этой проблемы было добавить

Response.TrySkipIisCustomErrors = true;

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

Найдено через Рика Стрэла http://www.west-wind.com/ блог / сообщений / 745738.aspx

Решение 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

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

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

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

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

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

Мне удалось обойти эту проблему с помощью следующей настройки в веб-формах 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 (), потому что почти каждая ошибка будет заключена в исключение более высокого уровня. Например, выполните & Quot; throw new System.Exception () & Quot; с любой страницы aspx приведет к получению исключения HttpUnhandledException на этом уровне, а не System.Exception.

" factory " код прост и выглядит так:

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();
    }

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

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

scroll top