Dans le feu de l’action, il nous arrive tous de faire des trucs un peu risibles. D’être pris dans un problème que l’on n’arrive pas à trouver une solution. Une spirale sans fin où la bonne solution n’est jamais vraiment à portée de main.
Ce qui est frustrant, c’est surtout de ne pas être en mesure de trouver la solution soi-même. Inévitablement, il faut avoir recours au fameux canard jaune.
D’ailleurs, à titre de précision, je ne suis pas le héros de cette histoire. J’en ai été néanmoins un témoin de premier ordre, car j’ai été invité à réviser du code lorsque la solution ne fonctionnait pas. Dans les faits, j’ai été le premier champion sur un seul candidat à trouver l’origine du bobo.
Bref, l’histoire ressemble à beaucoup d’autres histoires où ASP.NET MVC n’est pas capable de binder le modèle que l’on essaie de lui envoyer par un POST HTTP. À tous les coups le modèle assigné à l’action MVC était null.
Nous avions vérifié pour la présence des signaux de fumée usuels. C’est à dire:
- Le nom des variables du formulaire d’où provient le POST correspond à celles du modèle (en respectant la casse, même si ce n’est pas vraiment nécessaire)
- Que la requête utilise le bon verbe HTTP (POST, dans notre cas)
- Que le formulaire envoie à la bonne action MVC (faire appel à UrlHelper.Action pour automatiser le tout)
Or, il n’y a pas de façon autrement que gênante de présenter le code qui causait le problème. Tout est en lien avec le modèle envoyé à la méthode MVC qui prenait la forme suivante.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class UserModel | |
{ | |
public string Name; | |
public string Age; | |
public string City; | |
} |
Si vous faites du MVC sur une base relativement régulière, vous pouvez voir qu’il y a quelque chose qui cloche dans ce code. Il manque quelque chose de fondamental à cette classe. Les attributs permettant de faire que les variables publiques soient des propriétés automatiques ({get; set;}) ne sont pas présents.
Il faut donner un peu de crédit à l’auteur original. La classe en question était un peu loin dans la solution Visual Studio. Comme on dit par chez nous: il l’avait perdu de vue.
Cependant, c’est bien beau de rire un peu. Savez-vous pourquoi il est nécessaire d’avoir des propriétés automatiques dans vos classes de modèle? Après tout, une variable publique est accessible lorsque l’on manipule une instance de cette classe, n’est-ce pas?
La réponse est en lien avec la façon que MVC s’y prend pour aller hydrater un modèle envoyé à une action. Lorsqu’on y pense bien comme il faut, il serait logique que cela passe par réflexion pour aller récupérer les différentes propriétés à hydrater.
La twist c’est que dans le code que j’ai fourni ci-haut, il ne s’agit pas de propriétés automatiques. Il s’agit, en fait, de simples champs publics. Pour .NET, ce n’est pas du tout la même chose.
Une fois que nous avons converti les champs publics en propriétés automatiques, le résultat a été un succès instantané. Comme prévu.
Comme quoi qu’une revue de code peut faire réellement la différence. Pensez-y.
2 réflexions sur “L’histoire d’un ruberducking et ASP.NET MVC”