72 votes

ASP.NET MVC - Route de capture tout et route par défaut

En essayant de faire en sorte que mon application produise correctement des erreurs 404, j'ai mis en place une route catch-all à la fin de ma table de routes, comme indiqué ci-dessous:

 routes.MapRoute(
            "NotFound", _
           "{*url}", _
           New With {.controller = "Error", .action = "PageNotFound"} _
       )

Cependant, pour que cela fonctionne, j'ai dû supprimer la route par défaut:

{controller}/action/{id}

Mais maintenant que la route par défaut a été supprimée, la plupart de mes liens d'action ne fonctionnent plus, et la seule façon que j'ai trouvée pour les faire fonctionner à nouveau est d'ajouter des routes individuelles pour chaque contrôleur/action.

Existe-t-il un moyen plus simple de faire cela, plutôt que d'ajouter une route pour chaque contrôleur/action?

Est-il possible de créer une route par défaut qui permet toujours à la route catch-all de fonctionner si l'utilisateur essaie de naviguer vers une route inconnue?

1 votes

Pourquoi pensez-vous que le 404 ne fonctionnait pas correctement?

0 votes

@quakkels, J'ai eu la même plainte que @Sean. ASP.NET lance une erreur 404 puis effectue une redirection 302, donc le résultat n'est pas un vrai 404 sur la page en question. Cela se produit lors de l'utilisation de customErrors.

0 votes

@Dustin Oui, c'est le même problème que j'ai trouvé. Je ne pense pas que ce soit SEO friendly

111voto

Robert Koritnik Points 45499

Utiliser des contraintes de route

Dans votre cas, vous devriez définir votre route par défaut {controller}/{action}/{id} et y mettre une contrainte. Probablement liée aux noms des contrôleurs ou peut-être même des actions. Ensuite, mettez la route "attrape-tout" juste après et cela devrait fonctionner très bien.

Ainsi, lorsque quelqu'un demanderait une ressource qui ne respecte pas une contrainte, la route "attrape-tout" correspondrait à la demande.

Alors. Définissez d'abord votre route par défaut avec des contraintes de route, puis la route attrape-tout après :

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = "Home|Settings|General|..." } // c'est essentiellement une expression régulière
);
routes.MapRoute(
    "NotFound",
    "{*url}",
    new { controller = "Error", action = "PageNotFound" }
);

0 votes

Bon point. Je pensais que la première route ne correspondrait que si le nom du contrôleur correspondait... Merci!

0 votes

@andreirinea non, la carte de routage ne vérifie pas les types. Elle vérifie seulement si l'URL de la requête actuelle correspond à la correspondance. La seule chose que chaque route vérifie sont les contraintes lorsqu'elles sont présentes.

16 votes

Vous pourriez utiliser la réflexion pour créer votre contrainte de contrôleur et ainsi éviter une charge de maintenance à chaque fois que vous ajoutez un nouveau contrôleur. private static string GetAllControllersAsRegex() { var controllers = typeof(MvcApplication).Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Controller))); var controllerNames = controllers.Select(c => c.Name.Replace("Controller", "")); return string.Format("({0})", string.Join("|", controllerNames)); }

23voto

Praveen Prasad Points 13137
// Ceci capture toutes les demandes
routes.MapRoute(
    "Erreur",
    "{*.}",
     new { controller = "PublicDisplay", action = "Error404" } 
);

Ajoutez cette route à la fin de la table des routes

6 votes

Certainement, cela capture toutes les demandes. Mais si vous le déclarez avant la route par défaut, il remplacera la route par défaut et si vous le déclarez après la route par défaut, il ne sera pas appelé car la route par défaut capture la demande.

2 votes

"{*.*}", a fonctionné pour moi sur asp.net vb comme solution globale.

0 votes

"{*.}" ne capturait que les routes sans extension pour moi. J'ai changé en "{*.*}" pour capturer toutes les routes, y compris .aspx.

7voto

Haacked Points 31070

Ah, le problème est que votre route par défaut attrape toutes les URL à 3 segments. Le problème ici est que le routage s'exécute bien avant que nous déterminions qui va gérer la demande. Ainsi, toute URL à trois segments correspondra à la route par défaut, même s'il apparaît plus tard qu'il n'y a pas de contrôleur pour le gérer.

Une chose que vous pouvez faire est de remplacer la méthode HandleMissingAction de votre contrôleur. Vous devriez également utiliser la balise 404 pour gérer tous les problèmes 404.

2voto

Dustin Laine Points 22815

Eh bien, ce que j'ai trouvé, c'est qu'il n'y a pas de bonne manière de le faire. J'ai configuré la propriété redirectMode de customErrors à ResponseRewrite.

Cela me donne le comportement recherché, mais n'affiche pas la page formatée.

Pour moi, cela est mal fait en termes de SEO. Cependant, je pense qu'il existe une solution que je ne vois pas car SO fait exactement ce que je veux qu'il se produise. L'URL reste sur la page en erreur et renvoie une 404. Inspectez stackoverflow.com/fail dans Firebug.

0 votes

Drôle que vous ayez dit ça, lorsque j'ai commencé à examiner le problème, j'ai d'abord vérifié comment SO le gère. Je pourrais ajouter manuellement des routes pour chaque action, mais je pense que cela serait difficile à maintenir avec le temps. Je pense vraiment que MS pourrait fournir de meilleures orientations sur la question.

3 votes

Peut-être si nous demandons gentiment à Jeff, il le partagera avec nous ? :)

0 votes

Après avoir cherché longtemps, essayé diverses solutions, celle-ci semble fonctionner correctement pour moi. stackoverflow.com/questions/619895/…

0voto

Wyatt Barnett Points 12541

Vous êtes probablement mieux configuré le document d'erreur 404 dans la section de configuration, puis de restaurer l'itinéraire par défaut.

Pour ce que ça vaut, je pense que l'exigence de l'itinéraire par défaut est ridicule aussi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X