MVC 3 – Routing – Partie 8

Nous avons vu dans les articles précédents comment traiter les URL’s selon les différentes parties qui peuvent les composer. Désormais on voudrait ajouter des contraintes dans la syntaxe de ces parties.

1) Contraindre par les expressions régulières

La première solution pour contraindre la syntaxe de nos parties d’URL’s se fait via l’utilisation des expressions régulières. Tout simplement la méthode MapRoute peut prendre en paramètre des contraintes. Dans l’exemple suivant on souhaite traiter seulement les URL’s dont le nom du contoller commence par un H (donc répondant tout à fait à notre controller Home).

 public static void RegisterRoutes(RouteCollection routes)
 {
   Route rt = routes.MapRoute("Route 2",
         "{controller}/{action}/{pseudonyme}/{*poubelle}",
         new { controller = "Home", action = "Index", pseudonyme = UrlParameter.Optional },
         new { controller = "^H.*" },
         new[] { "TestMVCRouting.Controllers" });
 }

Ainsi toute URL avec une partie controller débutant par H sera interceptée par cette règle.

Bien noté la syntaxe des contraintes qui, comme celle des valeurs par défaut, utilise un type anonyme. A noter également dans le cas où ce sont les valeurs par défaut qui sont utilisées alors cette valeur par défaut sera comparée à la contrainte donnée…ce qui peut vite entraîner des erreurs (Dans notre cas par exemple mettre Test comme controller par défaut et non Home).

Etant donné qu’on utilise les expressions régulières les possibilités sont quasiment infinies. Nous pourrions tout à fait contraindre le pseudonyme comme suit :

Prenons une règle stupide stipulant que la partie pseudonyme doit être soit Jean soit Alain. L’expression régulière serait de la forme :

new { controller = "^H.*", pseudonyme="^Jean$|^Alain$" },

Maintenant en testant l’URL Home/Index/Jean ça fonctionne, en revanche Home/Index/Bertrand alors là l’application nous renvoie l’erreur 404. Ce système est donc vraiment très pratique mais peut vite devenir un vrai casse-tête.

2) Contraindre par les méthodes HTTP

Il est également possible de restreindre les URL’s via la méthode HTTP utilisée (GET ou POST). Cela se fait également dans le paramètre de MapRoute dans lequel nous avons auparavant ajouté des expressions régulières. Etant donné que l’on utilise un type anonyme il faut donner un nom à la propriété, en fait le framework MVC 3 se fout du nom de cette propriété tant qu’un objet de type HttpMethodConstraint lui est assignée. Voici un exemple pour ne prendre que les méthodes GET (j’ai enlevé la contrainte sur la partie pseudonyme car elle était stupide !).

new { controller = "^H.*", methodeHttp = new HttpMethodConstraint("GET") }

On relance l’application et effectivement ça fonctionne. Vous pouvez bien entendu vous amuser à mettre POST mais là l’application explosera car nous adressons en GET.

3) Contraintes définies par code

Et voilà la dernière partie de cet article. Si avec les contraintes par expressions régulières et les contraintes par méthode HTTP vous n’en avez pas assez vous pouvez également définir vos propres contraintes. Comme nous sommes très chauvins je voudrais interdire l’accès au site au personnes n’ayant pas un navigateur supportant le Français ! Il faut tout d’abord définir une classe héritant de l’interface IRouteConstraint. Cette interface nous oblige à implémenter la méthode Match qui va vérifier notre contrainte. Pour que ma contrainte soit un tant soit peu dynamique je vais passer en paramètre la langue que je souhaite vérifier. Voici l’exemple du code de ma nouvelle classe LangueNavigateurConstraint :

public class LangueNavigateurConstraint : IRouteConstraint
{
        private string langueContrainte = string.Empty;

        public LangueNavigateurConstraint(string pLangueContrainte)
        {
            this.langueContrainte = pLangueContrainte;
        }
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            return httpContext.Request.UserLanguages.Count(el => el.Contains(this.langueContrainte)) > 0;
        }
}

Et voilà le tour est joué, la méthode Match va aller regarder dans le contexte HTTP si dans les langages supportés l’un d’entre eux contient bien FR.

Maintenant il faut ajouter cette contrainte à notre type anonyme dans le global.asax.cs. Il est bien entendu possible d’ajouter autant de contraintes définies que l’on veut.

public static void RegisterRoutes(RouteCollection routes)
        {
            Route rt = routes.MapRoute("Route 2",
                "{controller}/{action}/{pseudonyme}/{*poubelle}",
                new { controller = "Home", action = "Index", pseudonyme = UrlParameter.Optional },
                new
                {
                    controller = "^H.*",
                    methodeHttp = new HttpMethodConstraint("GET"),
                    langueConstraint = new LangueNavigateurConstraint("FR")
                },
                new[] { "TestMVCRouting.Controllers" });
        }

Leave a Reply