web-dev-qa-db-fra.com

ASP.NET MVC - Intercepter toutes les routes et les routes par défaut

Pour que mon application produise correctement les erreurs 404, j'ai implémenté une capture de tous les itinéraires à la fin de mon tableau de routage, comme indiqué ci-dessous:

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

Cependant, pour que cela fonctionne, je devais supprimer la route par défaut:

{controller}/action/{id}

Mais maintenant que la valeur par défaut a été supprimée, la plupart de mes liens d'action ne fonctionnent plus, et le seul moyen que j'ai trouvé pour les faire fonctionner à nouveau est d'ajouter des itinéraires individuels pour chaque contrôleur/action. 

Existe-t-il un moyen plus simple de procéder, 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 capture de toutes les routes de fonctionner si l'utilisateur tente de naviguer vers une route inconnue?

61
Sean Taylor

Utiliser les contraintes de route

Dans votre cas, vous devez définir votre route par défaut {controller}/{action}/{id} et y appliquer une contrainte. Probablement lié aux noms des contrôleurs ou peut-être même aux actions. Ensuite, placez la capture toutes les suivantes et cela devrait fonctionner correctement.

Ainsi, lorsque quelqu'un demanderait une ressource qui échouait à une contrainte, la voie d'accès générale correspondrait à la demande.

Alors. Définissez d’abord votre route par défaut avec les contraintes de route, puis la route suivante:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = "Home|Settings|General|..." } // this is basically a regular expression
);
routes.MapRoute(
    "NotFound",
    "{*url}",
    new { controller = "Error", action = "PageNotFound" }
);
97
Robert Koritnik
//this catches all  requests
routes.MapRoute(
    "Error",
    "{*.}",
     new { controller = "PublicDisplay", action = "Error404" } 
);

ajouter cette route à la fin de la table des routes

17
Praveen Prasad

Ah, le problème est que votre route par défaut capture les 3 URL de segment . Le problème ici est que le routage fonctionne 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 si elle se termine plus tard, aucun contrôleur ne la gère.

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

7
Haacked

Eh bien, ce que j’ai trouvé, c’est qu’il n’ya pas de bonne façon de le faire. J'ai défini la propriété redirectMode de customErrors sur ResponseRewrite.

<customErrors mode="On" defaultRedirect="~/Shared/Error" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="~/Shared/PageNotFound"/>
</customErrors>

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

Pour moi, cela est mal fait, en ce qui concerne le référencement. Cependant, j’ai le sentiment qu’il me manque une solution car SO fait exactement ce que je veux. L'URL reste sur la page en échec et génère un 404. Inspectez stackoverflow.com/fail dans Firebug.

2
Dustin Laine

Je recommanderais ceci comme version la plus lisible. Vous en avez besoin dans votre RouteConfig.cs et d'un contrôleur appelé ErrorController.cs, contenant une action 'PageNotFound'. Cela peut retourner une vue. Créez un PageNotFound.cshtml, qui sera renvoyé en réponse à la 404:

        routes.MapRoute(
            name:  "PageNotFound",
            url:  "{*url}",
            defaults: new { controller = "Error", action = "PageNotFound" }
        );

Comment lire ceci:

name: "PageNotFound"

= créer un nouveau modèle de route, avec le nom arbitraire 'PageNotFound'

url:"{*url}"

= utiliser ce modèle pour mapper tous les itinéraires autrement non gérés

defaults: new { controller = "Error", action = "PageNotFound" }

= définit l’action à laquelle un chemin incorrect mappera (la méthode d’action 'PageNotFound' dans le contrôleur d’erreur). Cela est nécessaire car un chemin mal saisi ne sera évidemment pas mappé à une méthode d'action

1
Chris Halcrow

Si vous recherchez ASP.NET Core, accédez à tous les itinéraires et recherchez Google pour asp.net core catch all route vous amène ici:

ASP.net base MVC intercepte tous les fichiers statiques du service route

0
ostati

Il est probablement préférable de configurer le document d'erreur 404 dans la section de la configuration, puis de restaurer l'itinéraire par défaut.

FWIW, je pense que l’exigence de route par défaut est également retardée.

0
Wyatt Barnett

Ma solution est 2 étapes.

J'ai initialement résolu ce problème en ajoutant cette fonction à mon fichier Global.asax.cs:

protected void Application_Error(Object sender, EventArgs e)

Où j’ai essayé de convertir Server.GetLastError () en une exception HttpException, puis de vérifier GetHttpCode . Cette solution est détaillée ici:

Erreur personnalisée ASP.NET MVC lors de la gestion Application_Error Global.asax?

Ce n'est pas la source originale où j'ai eu le code. Cependant, cela ne récupère que 404 erreurs déjà routées. Dans mon cas, il s'agit d'une URL de niveau 2.

par exemple, ces URL afficheraient la page 404:

www.site.com/blah

www.site.com/blah/blah

cependant, www.site.com/blah/blah/blah dirait simplement que la page est introuvable… .. L'ajout de votre capture à tous les itinéraires APRÈS tous mes autres itinéraires a résolu ce problème:

routes.MapRoute(
            "NotFound",
            "{*url}",
            new { controller = "Errors", action = "Http404" }
        );

Cependant, la route NotFound ne semble pas acheminer les demandes qui ont des extensions de fichier. Cela fonctionne quand ils sont capturés par des itinéraires différents.

0
Marcus10110