ASP.NET Custom 404 повертає 200 OK замість 404 не знайдено


80

Спробувавши налаштувати свій сайт на Інструменти для веб-майстрів 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.
Боббі Кеннон,

Відповідь шпигуна заголовка: HTTP / 1.1 404 Не знайдено Дата: Нд, 07 грудня 2008, 06:21:20 за Гринвічем
Райан Кук,

Ви використовуєте головну сторінку? Можливо, це все. Я спробую сторінку, не використовуючи головну сторінку ...
Боббі Кеннон,

Ні, я не був, але я можу також швидко зробити перевірку, спробую за допомогою однієї.
Райан Кук,

Так, ось і все! Головна сторінка спричинила 200 ОК
Райан Кук

Відповіді:


72

Рішення:

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

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

4
Header Spy - це аддон Header Spy для Firefox
Kiquenet

Як це працює для статичних .htmlсторінок користувацьких помилок?
ебіроб

28

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

Рішенням цього було додати

Response.TrySkipIisCustomErrors = true;

Перед зміною Response.StatusCode.

Знайдено через Ріка Штраля http://www.west-wind.com/weblog/posts/745738.aspx


12

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


3
Працював у мене! Єдине рішення, яке спрацювало, можливо, завдяки версії, яку ви зазначаєте ... Майте на увазі: з цим рішенням ви можете використовувати лише статичні файли .htm.
squarecandy

11

Спробуйте зателефонувати Response.End (), щоб пропустити візуалізацію ...

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

9

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

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

Це дозволить сторінці повернути правильний код повернення, незважаючи ні на що.


1

Мені вдалося обійти цю проблему, використовуючи такі налаштування у веб-формах asp.net за допомогою .NET 3.5.

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

По-перше, розділ customErrors web.config виглядає так:

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

Це налаштування гарантує, що для режиму CustomErrors увімкнено параметр, який нам знадобиться пізніше, і надає опцію "все-ще-невдачі" для 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 () на цьому рівні, оскільки майже кожна помилка буде загорнута у виняток вищого рівня. Наприклад, якщо "кинути новий 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, а також відповідний код стану, записаний у заголовку.

Сподіваюся, це допомагає.


0

Ви можете використовувати наведений нижче код:

 Response.TrySkipIisCustomErrors = True
 Response.Status = "404 Not Found"
 Response.AddHeader("Location", "{your-path-to-your-404-page}")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.