2008-10-25 12 views
16

Quelle est la meilleure façon de gérer un visiteur en construisant sa propre URL et en remplaçant ce que nous attendons d'être un ID avec ce qu'il veut?ASP.Net MVC - gérer les mauvais paramètres d'URL

Par exemple:

ASP.Net MVC - handling bad URL parameters

Mais l'utilisateur peut aussi remplacer facilement l'URL avec:

https://stackoverflow.com/questions/foo

J'ai pensé à faire tous les paramètres du contrôleur de fonction d'un String, et en utilisant Integer.TryParse() sur eux - si cela passe alors j'ai un ID et peut continuer, sinon je peux rediriger l'utilisateur vers une vue Unknown/not-found ou index. Stack Overflow le gère bien, et j'aimerais aussi - comment le faites-vous, ou que suggérez-vous?

Répondre

12

Voici un exemple d'une route comme la vôtre, avec une contrainte sur le nombre:

routes.MapRoute(
    "Question", 
    "questions/{questionID}", 
    new { controller = "StackOverflow", action = "Question" }, 
    new { questionID = @"\d+" } //Regex constraint specifying that it must be a number. 
); 

Ici nous avons mis le QuestionID d'avoir au moins un numéro. Cela permettra également de bloquer toutes les URL contenant tout sauf un entier, et empêche également la nécessité d'un int nullable.

Remarque: Ceci ne prend pas en compte les nombres supérieurs à la plage de Int32 (-2147483647 - +2147483647). Je laisse cela comme un exercice à l'utilisateur à résoudre. :)

Si l'utilisateur entre l'url "questions/foo", il ne touchera pas l'action Question et tombera dessus, car il échoue à la contrainte du paramètre. Vous pouvez gérer plus bas dans une voie catchall/default si vous voulez:

routes.MapRoute(
    "Catchall", 
    "{*catchall}", // This is a wildcard routes 
    new { controller = "Home", action = "Lost" } 
); 

Cela envoie l'utilisateur à l'action perdue dans le contrôleur de la maison. Plus d'informations sur le caractère générique peut être trouvé here.

NB: Le Catchall devrait résider comme la dernière LAST. En le plaçant plus haut dans la chaîne, cela signifiera que cela gèrera tous les autres en dessous, étant donné la nature paresseuse des routes dans ASP.NET MVC.

+2

cela ressemble à un très bon moyen de gérer les utilisateurs fous =) – JOBG

+2

Au lieu de cette dernière ligne: 'new {questionID = @ "\ d {1,}"}', Scott Hanselman utilise une syntaxe légèrement plus courte de: 'new { questionID = @ "\ d +"} 'signifie la même chose. Source: http://www.asp.net/learn/mvc-videos/video-7093.aspx – Andrew

+1

Oui, les deux sont à peu près la même chose. J'ai tendance à mettre le mien entre accolades comme ça parce que je crée dynamiquement mes routes à partir de la base de données, et cela me sauve un peu de logique quand je veux spécifier explicitement le nombre maximum de chiffres. –

0

Le problème avec cette approche est qu'ils peuvent toujours passer un entier qui ne correspond pas à une page. Renvoyez juste un 404 s'ils le font, comme vous le feriez avec "foo". Ce n'est pas quelque chose à s'inquiéter à moins que vous ayez des implications de sécurité claires.

+0

Bien sûr, je devrais vérifier que le nombre entier est valide, mais utilise la chaîne comme type de paramètre de fonction le chemin à parcourir? - L'exemple TaskList (http://www.asp.net/learn/mvc/tutorial-01-cs.aspx ~ 35min 43s) tape fortement l'ID en Integer, ce qui entraîne une erreur lorsque 'foo' est transmis: o/ – Andrew

3

Dans ASP.NET MVC, vous pouvez définir un filtre implémentant l'interface IActionFilter. Vous serez en mesure de décorer votre action avec cet attribut afin qu'il soit exécuté sur, avant ou après votre action.

Dans votre cas, vous allez le définir pour être exécuté "avant" votre action. Donc, vous serez en mesure de l'annuler s'il y a une erreur dans les paramètres passés. Le principal avantage est que vous n'écrivez que le code qui vérifie une fois les paramètres passés (c'est-à-dire que vous le définissez dans votre filtre) et l'utilisez où vous voulez dans les actions de votre contrôleur.

En savoir plus sur les filtres MVC ici: http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx

2

Vous pouvez spécifier des contraintes comme des expressions régulières ou définir des contraintes personnalisées. Jetez un coup d'oeil à ce blog pour plus d'informations:

http://weblogs.asp.net/stephenwalther/archive/2008/08/06/asp-net-mvc-tip-30-create-custom-route-constraints.aspx

Vous aurez toujours besoin pour faire face à la situation dans laquelle 43243 id ne correspond pas à quoi que ce soit qui pourrait être traitée comme un IActionFilter ou dans votre contrôleur directement.

5

Voici quelques informations utiles qui pourraient vous aider. Si vous avez une méthode d'action

public ActionResult Edit(int? id) 
{} 

alors si quelqu'un tape

/Home/Edit/23 

l'identifiant du paramètre sera 23. si quelqu'un tape

/Home/Edit/Junk 

alors id aura null ce qui est plutôt cool. Je pensais que ça jetterait une erreur de casting ou quelque chose comme ça. Cela signifie que si id n'est pas une valeur nulle alors c'est un entier valide et peut être passé à vos services etc. pour l'interaction db.

J'espère que cela vous fournit des informations que j'ai trouvées lors des tests.

+0

De plus, il y aura une erreur de modèle présente dans ModelState qui reflète le problème avec le paramètre "id". –