web-dev-qa-db-fra.com

Meilleure façon d'implémenter un 404 dans ASP.NET

J'essaie de déterminer la meilleure façon d'implémenter une page 404 dans une application Web ASP.NET standard. J'attrape actuellement des erreurs 404 dans l'événement Application_Error dans le fichier Global.asax et je redirige vers une page 404.aspx conviviale. Le problème est que la demande voit une redirection 302 suivie d'une page 404 manquante. Existe-t-il un moyen de contourner la redirection et de répondre avec un 404 immédiat contenant le message d'erreur convivial?

Un robot d'indexation tel que Googlebot se soucie-t-il si la demande d'une page inexistante renvoie un 302 suivi d'un 404?

35
Ben Mills

Gérez cela dans votre événement OnError de Global.asax:

protected void Application_Error(object sender, EventArgs e){
  // An error has occured on a .Net page.
  var serverError = Server.GetLastError() as HttpException;

  if (serverError != null){
    if (serverError.GetHttpCode() == 404){
      Server.ClearError();
      Server.Transfer("/Errors/404.aspx");
    }
  }
}

Dans votre page d'erreur, vous devez vous assurer que vous définissez correctement le code d'état:

// If you're running under IIS 7 in Integrated mode set use this line to override
// IIS errors:
Response.TrySkipIisCustomErrors = true;

// Set status code and message; you could also use the HttpStatusCode enum:
// System.Net.HttpStatusCode.NotFound
Response.StatusCode = 404;
Response.StatusDescription = "Page not found";

Vous pouvez également très bien gérer les divers autres codes d'erreur ici.

Google suivra généralement le 302, puis honorera le code d'état 404 - vous devez donc vous assurer de le renvoyer sur votre page d'erreur.

43
Zhaph - Ben Duguid

Vous pouvez utiliser le web.config pour envoyer des erreurs 404 à une page personnalisée.

    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
        <error statusCode="403" redirect="NoAccess.htm" />
        <error statusCode="404" redirect="FileNotFound.htm" />
    </customErrors>
14
Robin Day

J'aime vraiment cette approche: elle crée une vue unique pour gérer tous les types d'erreur et remplace IIS.

[1]: Supprimez tous les "customErrors" et "httpErrors" de Web.config

[2]: Vérifiez que 'App_Start/FilterConfig.cs' ressemble à ceci:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

[3]: dans 'Global.asax' ajoutez cette méthode:

public void Application_Error(Object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    var routeData = new RouteData();
    routeData.Values.Add("controller", "ErrorPage");
    routeData.Values.Add("action", "Error");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    Response.TrySkipIisCustomErrors = true;
    IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

[4]: Ajoutez 'Controllers/ErrorPageController.cs'

public class ErrorPageController : Controller
{
    public ActionResult Error(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        ViewBag.StatusCode = statusCode + " Error";
        return View();
    }
}

[5]: dans 'Vues/Partagé/Erreur.cshtml'

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}

 <h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>


//@Model.ActionName
//@Model.ContollerName
//@Model.Exception.Message
//@Model.Exception.StackTrace

:RÉ

3
ubik404

J'ai également rencontré 302 au lieu de 404. J'ai réussi à le réparer en procédant comme suit:

Contrôleur:

public ViewResult Display404NotFoundPage()
        {
            Response.StatusCode = 404;  // this line fixed it.

            return View();
        }

Voir:

Afficher un message d'erreur à l'utilisateur.

web.config:

<customErrors mode="On"  redirectMode="ResponseRedirect">
      <error statusCode="404" redirect="~/404NotFound/" />
</customErrors>

Enfin, le RouthConfig:

routes.MapRoute(
             name: "ErrorPage",
             url: "404NotFound/",
             defaults: new { controller = "Pages", action = "Display404NotFoundPage" }
         );
3
Eyal

Réponse la plus simple: ne le faites pas en code, mais configurez IIS à la place .

3
Pontus Gagge

Je peux voir que la configuration de la page 404 dans le web.config est une belle méthode propre, MAIS elle répond toujours initialement par une redirection 302 vers la page d'erreur. Par exemple, si vous accédez à:

https://stackoverflow.com/x.aspx

vous serez redirigé via une redirection 302 vers:

https://stackoverflow.com/404?aspxerrorpath=/x.aspx

Ce que je veux arriver, c'est ceci:

http://www.cnn.com/x.aspx

Il n'y a pas de redirection. Une demande d'URL manquante renvoie un code d'état 404 avec un message d'erreur convivial.

2
Ben Mills

L'utilisez-vous n'importe où?

 Response.Status="404 Page Not Found"
2
inspite

Vous pouvez configurer IIS lui-même pour renvoyer des pages spécifiques en réponse à tout type d'erreur http (404 inclus).

0
Assaf Lavie

Je pense que la meilleure façon est d'utiliser la construction d'erreurs personnalisées dans votre web.config comme ci-dessous, cela vous permet de câbler des pages pour gérer tous les différents codes HTTP d'une manière simple et efficace.

  <customErrors mode="On" defaultRedirect="~/500.aspx">
     <error statusCode="404" redirect="~/404.aspx" />
     <error statusCode="500" redirect="~/500.aspx" />
  </customErrors>
0
James