Question

Après avoir essayé de configurer mon site pour Google Webmaster Tools, j'ai constaté que ma page ASP.NET 404 personnalisée ne renvoyait pas le code d'état 404. Il affiche la page personnalisée correcte et indique au navigateur que tout va bien. Ceci est considéré comme un soft 404 ou un faux 404. Google n'aime pas cela. J'ai donc trouvé de nombreux articles sur le sujet, mais la solution que je souhaitais ne semblait pas fonctionner.

La solution que je souhaite travailler consiste à ajouter les deux lignes suivantes au code situé derrière la méthode Page_Load de la page 404 personnalisée.

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

Cela ne fonctionne pas. La page retourne toujours 200 OK. J'ai cependant constaté que si je codais en dur le code suivant dans le code de conception, il fonctionnerait correctement.

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

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

 ... Much more code ...

</asp:content>

La page utilise une page maître. Et je configure des pages d'erreur personnalisées dans mon web.config. Je préférerais vraiment utiliser le code derrière l'option, mais je n'arrive pas à le faire fonctionner sans mettre le code en ligne hack dans la conception / la présentation.

Était-ce utile?

La solution

Solution:

Le problème, s’est avéré, était l’utilisation de la page maître. Je l’ai obtenu en définissant le code d’état plus tard dans le cycle de vie des pages. De toute évidence, le rendu de la page maître était en train de le réinitialiser. J'ai donc surchargé la méthode de rendu et je l'ai défini une fois le rendu terminé.

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

D'autres travaux pourraient être faits pour savoir exactement quand la page maître définit l'état, mais je vous laisse cela.

Message d'origine:

J'ai réussi à faire fonctionner une application web de test. Elle a au moins affiché la page d'erreur personnalisée et renvoyé un code d'état 404. Je ne peux pas vous dire ce qui ne va pas avec votre application, mais je peux vous dire ce que j'ai fait:

1) Modifié le fichier web.config pour les erreurs personnalisées:

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

2) Ajout d'une page 404.aspx et définition du code d'état sur 404.

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

C'est à peu près tout, si je vais à n'importe quelle extension de page traitée par Asp.Net et qui n'existe pas, mon journal de violoniste affiche clairement un 404, voici l'en-tête:

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

Maintenant, si je vais à une page qui n'est pas traitée par Asp.Net, comme un fichier htm, la page personnalisée ne s'affiche pas et le 404 configuré par IIS s'affiche.

Voici un article qui contient plus de détails qui pourraient vous être utiles, ainsi que votre problème. Mon test effectue une redirection vers la nouvelle page, de sorte que l'URL du fichier demandé est pratiquement perdue (à l'exception de sa chaîne de requête).

Pages d'erreur personnalisées Google 404 et .NET

Réponse de l'espion en-tête:

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT

Autres conseils

J'avais un problème similaire. Je souhaitais afficher une page personnalisée en tant que 404 (ASPX). Cela fonctionnait correctement sur localhost, mais dès qu'un visiteur distant se connectait, il obtiendrait le générique IIS 404.

La solution à cela a été d'ajouter

Response.TrySkipIisCustomErrors = true;

Avant de modifier le code Response.Status.

Trouvé via Rick Strahl http://www.west-wind.com/ weblog / posts / 745738.aspx

La solution IIS 7 consiste simplement à ajouter ceci à votre fichier 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 <

Essayez d'appeler Response.End () pour ignorer le rendu ...

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

Après de nombreux tests et dépannage, il apparaît que certains fournisseurs d’hébergement peuvent interférer avec le code de retour. J'ai pu contourner ce problème en appliquant un "hack". dans le contenu.

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

Cela permettra à la page de renvoyer le code de retour correct, quoi qu'il arrive.

J'ai pu résoudre ce problème en utilisant la configuration suivante dans les formulaires Web asp.net à l'aide de .NET 3.5.

Le modèle que j'ai mis en place contourne la solution de redirection personnalisée .NET dans le fichier web.config car j'ai moi-même écrit pour gérer tous les scénarios avec le code d'état HTTP correct dans l'en-tête.

Tout d'abord, la section customErrors du composant web.config se présente comme suit:

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

Cette configuration garantit que le mode CustomErrors est activé, paramètre dont nous aurons besoin ultérieurement, et fournit une option tout-autre-échec pour le paramètre defaultRedirect de error.htm. Cela me sera utile si je n'ai pas de gestionnaire pour l'erreur spécifique ou s'il y a quelque chose qui ressemble à une connexion de base de données rompue.

Deuxièmement, voici l'événement global 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();
    }
    }

Ce code dégage la responsabilité de la gestion de l'erreur vers une autre classe. Si l'erreur n'est pas gérée et que CustomErrors est activé, cela signifie que nous sommes en cours de production et que, d'une manière ou d'une autre, une erreur n'a pas été gérée. Nous allons le supprimer ici afin d'empêcher l'utilisateur de le voir, mais connectez-le à Elmah afin que nous sachions ce qui se passe.

La classe applicationErrorHandler se présente comme suit:

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

Cette classe utilise essentiellement le modèle de commande pour localiser le gestionnaire d’erreur approprié pour le type d’erreur généré. Il est important d'utiliser Exception.GetBaseException () à ce niveau, car presque chaque erreur sera encapsulée dans une exception de niveau supérieur. Par exemple, cliquez sur "Lancer une nouvelle System.Exception ()". depuis une page aspx, une exception HttpUnhandledException sera reçue à ce niveau, pas une exception System.Exception.

Le " usine " le code est simple et ressemble à ceci:

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

En fin de compte, j'ai mis en place un schéma de traitement des erreurs extensible. Dans chacun des & comportements; comportements " qui est défini, j’ai une implémentation personnalisée pour le type d’erreur. Par exemple, une exception HTTP sera inspectée pour le code de statut et traitée de manière appropriée. Un code d'état 404 nécessitera un Server.Transfer au lieu d'un Request.Redirect, ainsi que le code d'état approprié écrit dans l'en-tête.

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top