[ASP.NET MVC 2] [RESOLU] Problème de routage

Bonjour les amis.

Malgré un bagage WebForms assez important, je viens à peine d’aborder ASP.NET MVC.
Avec la sortie d’ASP.NET 4 et VS 2010 j’ai joué un peu avec le site de démo d’ASP.NET MVC 2 (le même que MVC “1”).

J’ai alors essayé d’ajouter un contrôleur de test, avec une action prenant en charge un paramètre wildcard.

Voici ma route ajoutée :

routes.MapRoute( "Test", "{controller}/{action}/{*pathInfo}", new { controller = "Test", action = "Browse" } );

Voici l’action de mon contrôleur :

public ActionResult Browse(String pathInfo) { ViewData["PathInfo"] = pathInfo; return View(); }

Et voici enfin ma vue :

[code]

Browse

PathInfo = <%: ViewData["PathInfo"] %>

[/code]

Absolument rien d’extraordinaire.

Je visite donc mon site, je lui passe le chemin “/Test/Browse/abc” et là… RIEN. pathInfo est null.

Je teste d’autres valeurs, et voici le résultat :
/Test/Browse donne pathInfo = null
/Test/Browse/ donne pathInfo = null
/Test/Browse/abc donne pathInfo = null
/Test/Browse/abc/ donne pathInfo = null
/Test/Browse/abc/def donne pathInfo = “abc/def”
/Test/Browse/abc/def/ghi donne pathInfo = “abc/def/ghi”

Le tout est reproduisible sur ce site :
http://dev4.smartgeek.net/Test/Browse

J’ai regardé la documentation, et il ne me semble pas être passé à côté de quelque chose :
http://msdn.microsoft.com/en-us/library/cc…n_a_url_pattern

[quote]query/{queryname}/{*queryvalues}

query/select/bikes/onsale
queryname = "select"
queryvalues = “bikes/onsale”

query/select/bikes
queryname = "select"
queryvalues = “bikes”[/quote]

C’est mes premiers essais avec ASP.NET MVC, et j’ai déjà un comportement différent de la doc, ça commence bien !

Chez moi ça marche

[code] routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

		routes.MapRoute(
			"Home-Browse", // Route name
			"Home/Browse/{*path}", // URL with parameters
			new { controller = "Home", action = "Browse", path = UrlParameter.Optional } // Parameter defaults
		);

		routes.MapRoute(
			"Default", // Route name
			"{controller}/{action}/{id}", // URL with parameters
			new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
		);[/code]

public ActionResult Browse(string path) { this.ViewData["path"] = path; return View(); }

/Home/Browse/test me donne bien path = test

Edit : ca marche aussi avec cette route :

[code]public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
	"Default", // Route name
	"{controller}/{action}/{*path}", // URL with parameters
	new { controller = "Home", action = "Index", path = UrlParameter.Optional } // Parameter defaults
);

}[/code]

Je suspecte quelque chose qu’il n’aime pas dans ta déclarations des routes, et qui fait qu’il utilise une autre route dans certains cas.

La seule différence avec ton code, c’est que ma route est ajoutée après celle par défaut.
Je l’ai ajoutée avant celle par défaut, et ça fonctionne !

Mais là franchement je pige pas pourquoi la route par défaut pouvait prendre le dessus :

[code]routes.IgnoreRoute(« {resource}.axd/{*pathInfo} »);

routes.MapRoute(
« Default », // Route name
« {controller}/{action}/{id} », // URL with parameters
new { controller = « Home », action = « Index », id = UrlParameter.Optional } // Parameter defaults
);

routes.MapRoute(
« Test-Browse »,
« {controller}/{action}/{*pathInfo} »,
new { controller = « Test », action = « Browse », pathInfo = UrlParameter.Optional }
);[/code]

Après avoir inversé l’ordre des routes, ça fonctionne… :smiley:

C’est pourtant ça.

Ce qu’il faut garder en tête, c’est que les règles de validation des routes ne prennent en compte que les règles, elles ne connaissent pas la signature de tes méthodes.

Dans la déclaration de la route par défaut toutes les url avec un paramètre simple (sans /) après l’action sont valides pour cette règle.

Une fois la règle déterminée, le framework cherche quelle méthode appeler, et affecte les valeurs décelées aux paramètres. du même nom.

Donc ta méthode ne possédant pas de paramètre « id », il l’invoquait sans passer de valeur.

Dans les cas où tu as un inclu un « / » dans pathInfo, la première règle n’est plus acceptée (le / est un séparateur), du coup tu tombes sur la seconde.

Pour comprendre et illustrer tout cela il t’aurait suffit de rajouter une paramètre string id à ta méthode, et tu aurais vu les valeurs apparaître. à l’exécution.

Edit : clarification.

Ok, j’ai compris à peu près.
Le soucis c’est quand même que malgré la mauvaise route, c’est mon contrôleur (« Test ») et mon action (« Browse ») qui étaient appelés pour retourner ma vue… Bref ça m’a pas aidé à comprendre. Maintenant je saurai faire attention aux patterns d’URLs utilisés dans mes routes.

Merci ! :smiley:

Il te faut bien piger le fonctionnement du dernier paramètre MapRoute. Il détermine le comportement à utiliser pour chaque segment.

Ce code signifie :

  • si le paramètre controller ne peut être déterminé depuis l’url, utilise “Home”
  • si le paramètre action ne peut être déterminé, utilise “Index”
  • le paramètre id est optionel.

Donc dans ton cas, tu précises bien le controller (“Test”) et l’action (“Browse”) dans ton url, du coup il n’y a aucune raison quelle ne soit pas matchée. Et le framework arrive très bien à trouver quelle méthode de quelle classe appeler.

Il faut savoir que la règle par défaut doit être celle qui s’applique tant qu’il n’y a pas de cas particulier. Donc tes cas particuliers tu les mets avant.

Et si tu souhaites qu’ils ne s’appliquent à un couple contrôleur/action, tu supprimes les paramètres {controller} et {action} de l’url et tu forces leurs valeur via le dernier paramètre de MapRoute.

Understood. C’est maintenant plus clair. Merci mastah !

Ily a un truc pour debugger ses routes qui est super utile.

http://haacked.com/archive/2008/03/13/url-…g-debugger.aspx

Avec ca c’est quand meme plus simple.