ASP.NET Custom 404 zwraca 200 OK zamiast 404 Not Found

Po próbie skonfigurowania mojej strony dla narzędzi dla webmasterów Google znalazłem, że mój Niestandardowy ASP.NET strona 404 nie zwracała kodu statusu 404. Wyświetlił poprawną stronę niestandardową i powiedział przeglądarce, że wszystko jest w porządku. Jest to tzw. soft 404 lub false 404. Google tego nie lubi. Więc znalazłem wiele artykułów na ten temat, ale rozwiązanie, które chcę, nie wydaje się działać.

Rozwiązaniem, które chcę pracować, jest dodanie następujących dwóch linii do kodu za metodą Page_Load strona 404.

Response.Status = "404 Not Found";
Response.StatusCode = 404;
To nie działa. Strona nadal zwraca 200 OK. Odkryłem jednak, że jeśli na twardo zakoduję poniższy kod do kodu projektu, będzie on działał poprawnie.
<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">

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

 ... Much more code ...

</asp:content>

Strona używa strony wzorcowej. I konfiguruję niestandardowe strony błędów w mojej sieci.config. Naprawdę wolałbym użyć kodu za opcją, ale nie wydaje mi się, aby to działało bez umieszczenia kodu włamania w projekcie / układzie.

Author: Bobby Cannon, 2008-12-07

6 answers

Rozwiązanie:

Okazało się, że problemem było użycie strony wzorcowej. Dostałem go do pracy, ustawiając kod stanu później w cyklu życia stron, oczywiście renderowanie strony wzorcowej było Resetowanie go, więc nadpisałem metodę render i ustawiłem ją po zakończeniu renderowania.

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

Można zrobić więcej pracy, aby dowiedzieć się, kiedy dokładnie strona wzorcowa ustawia status, ale zostawię to tobie.


Original Post:

I był w stanie uzyskać testową aplikację internetową, aby działała dobrze, dobrze przynajmniej wyświetlał niestandardową stronę błędu i zwrócił kod stanu 404. Nie mogę powiedzieć, co jest nie tak z aplikacji, ale mogę powiedzieć, co zrobiłem:

1) edytował www.config dla błędów niestandardowych:

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

2) Dodano 404.strony aspx i ustaw kod stanu na 404.

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

O to chodzi, jeśli przejdę do jakiegoś rozszerzenia strony, które jest przetwarzane przez Asp.Net i nie istnieje, mój dziennik skrzypka wyraźnie pokazuje 404, oto nagłówek:

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

Teraz, jeśli przejdę do strony, która nie jest przetwarzana przez Asp.Net podobnie jak plik htm, strona niestandardowa nie jest wyświetlana, a wyświetlany jest 404 skonfigurowany przez IIS.

Oto post, który przechodzi w kilka więcej szczegółów, które mogą być przydatne dla Ciebie i Twojego problemu, mój test robi przekierowanie na nową stronę, więc adres URL żądanego pliku jest prawie utracony(z wyjątkiem jego w ciągu zapytania).

Google 404 i. NET Custom Strony Błędów

Header Spy Response:

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
 69
Author: Ryan Cook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:00

Miałem podobny problem, chcę pokazać niestandardową stronę jako 404 (czyli ASPX) i działało dobrze na localhost, ale jak tylko zdalny gość połączyłby się, dostaliby ogólne IIS 404.

Rozwiązaniem było dodanie

Response.TrySkipIisCustomErrors = true;

Przed zmianą odpowiedzi.StatusCode.

Znalezione przez Rick Strahl http://www.west-wind.com/weblog/posts/745738.aspx

 27
Author: gary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 23:28:31

Rozwiązanie IIS 7 polega na dodaniu tego do swojej sieci.plik konfiguracyjny:

<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

 12
Author: Nick D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-03 08:05:06

Spróbuj wywołać odpowiedź.End (), aby pominąć renderowanie...

Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;
 10
Author: Jason Goemaat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-22 00:06:05

Po wielu testach i rozwiązywaniu problemów okazuje się, że niektórzy dostawcy hostingu mogą zakłócać kod zwrotny. Udało mi się to obejść, stosując "hack" w treści.

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

To pozwoli stronie zwrócić poprawny kod zwrotu bez względu na wszystko.

 6
Author: Bobby Cannon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-08 01:54:36

Udało mi się obejść ten problem, używając poniższej konfiguracji w asp.net webforms za pomocą. NET 3.5.

Zaimplementowany przeze mnie wzorzec omija niestandardowe rozwiązanie przekierowania.NET w sieci.config jak napisałem mój własny do obsługi wszystkich scenariuszy z poprawnym kodem statusu HTTP w nagłówku.

Po pierwsze, sieć.sekcja customErrors config wygląda tak:

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

Ta konfiguracja zapewnia, że tryb CustomErrors jest ustawiony na on, ustawienie, które będziemy potrzebować później, i zapewnia opcja all-else-fails dla defaultRedirect błędu.htm. Przyda się to, gdy nie mam obsługi konkretnego błędu lub jest coś w rodzaju uszkodzonego połączenia z bazą danych.

Po Drugie, oto globalne zdarzenie błędu asax:

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

Ten kod przenosi odpowiedzialność za obsługę błędu na inną klasę. Jeśli błąd nie jest obsługiwany i CustomErrors jest włączony, oznacza to, że mamy sprawę, w której jesteśmy na produkcji i jakoś błąd nikt się tym nie zajął. Wyczyścimy go tutaj, aby użytkownik nie mógł go zobaczyć, ale Zaloguj go w Elmah, abyśmy wiedzieli, co się dzieje.

Klasa applicationErrorHandler wygląda tak:

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

Ta klasa zasadniczo używa wzorca poleceń do zlokalizowania odpowiedniej obsługi błędów dla typu błędu, który został wydany. Ważne jest, aby używać WYJĄTKÓW.GetBaseException () na tym poziomie, ponieważ prawie każdy błąd będzie zawinięty w wyjątek wyższego poziomu. Na przykład, doing "rzuć nowy System.Exception()" z dowolnej strony aspx spowoduje, że na tym poziomie zostanie odebrane HttpUnhandledException, a nie System.Wyjątek.

Kod "fabryczny" jest prosty i wygląda tak:

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

W końcu mam rozszerzalny schemat obsługi błędów. W każdym z zdefiniowanych "zachowań" mam niestandardową implementację dla typu błędu. Na przykład wyjątek Http będzie sprawdzany pod kątem kodu stanu i odpowiednio obsługiwany. A 404 status kod będzie wymagał serwera.Przelew zamiast wniosku.Przekierowanie, wraz z odpowiednim kodem stanu zapisanym w nagłówku.

Mam nadzieję, że to pomoże.
 1
Author: letsgetsilly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-20 17:32:55