Prog
Custom Model Binding en ASP.net MVC
by F5 on nov.14, 2011, under Prog
Je m’essaye pour la première fois au tuto Asp.net MVC, soyez indulgent c’est ma toute première fois !
Derrière le nom barbare du titre se cache une technique élégante de SoC (Separation of Concern, qu’on pourra traduire par « séparation des fonctionnalités ») proposée par Microsoft pour commencer à faire du code propre faire en sorte que dans votre action de contrôleur il n’y ait pas de code de conversion de données de formulaires envoyées en HTTP en objet complexe, de parsing de chaine ou toute opération qui n’aurait rien à faire dans le beau code du contrôleur. Surtout quand on récupère des données sérialisées à la one-again par le mec du bureau d’en face qui développe le jquery/Ajax…
Pour la démo, admettons donc que vous soyiez en train de travailler sur un énorme backoffice contenant une page de malade mental ; page qui, au chargement, affiche un Guid généré par l’action initiale (Index) dans une Div, et qui permet de poster cette même donnée en Jquery/Ajax. 0 intérêt : c’est pour l’exemple ! Surtout qu’Asp.net MVC gère par défaut le cast de string à Guid… Mais bon !
Voici la vue en question (le moteur de vue est Razor, ‘What else ?’):
@model Back.Models.GuidModel
<html>
<script type="text/javascript" src="../../Content/js/jquery.1.6.2.min.js"></script>
<script>
$(function()
{
$("#submitAjax").one("click", function(e)
{
e.preventDefault();
$.post(
"RefreshIt/PostGuid",
{id:$("#leguid").text()},
function(data)
{
$("#messageRetour").text(data.message);
},
"json"
);
});
});
</script>
<body>
<div>Guid Client</div>
<div id="leguid">@Model.Guid</div>
<p><input type="button" id="submitAjax" value="Poster" /></p>
<p id="messageRetour"></p>
</body>
</html>Plutôt simpliste : la vue affiche le guid généré par le serveur, et en jquery il y a un post du guid contenu dans la div d’id « leguid » quand on clique sur le bouton et ça affiche le message de retour dans la balise p qui va bien.
Le modèle est quant à lui d’une grande complexité :
public class GuidModel
{
public Guid Guid { get; set; }
}
Enfin voici le code du contrôleur tel que l’aurait développé Mariah Carey :
public class RefreshItController : Controller
{
public ActionResult Index()
{
GuidModel model = new GuidModel {Guid = Guid.NewGuid()};
return View(model);
}
public ActionResult PostGuid(string inputGuidStr)
{
/* Code moche */
Guid inputGuid = Guid.Empty;
Guid.TryParse(inputGuidStr, out inputGuid);
/* Fin du code moche */
FaireQuelqueChoseAvec(inputGuid);
return Json(new { message = "All by myself..." });
}
private void FaireQuelqueChoseAvec(Guid inputGuid)
{
return;
}
}Je passe sur la vue Index qui ne fait qu’instancier le modèle.
C’est dans l’action PostGuid, appelée par le jquery qu’il y a un problème. En effet, cette action exécute en quelque sorte 2 choses :
- elle parse le string envoyé par jquery pour le caster en Guid
- elle redirige la demande vers un autre « service », ici symbolisé par la fonction « FaireQuelqueChoseAvec » (qui en pratique se trouvera certainement dans une autre assembly)
C’est mauvais. Le code de l’action serait bien plus beau s’il se contentait de transmettre de l’information, de la vue au service d’accès au données par exemple. Ici, il effectue une basse tâche de cast, qui pollue le contrôleur… alors qu’on sait qu’un contrôleur contient facilement un certain nombre d’actions et qu’il n’a pas besoin d’être surchargé de lignes de codes, surtout quand elles sont d’un niveau d’abstraction assez bas comme du vulgaire parsing de chaine.
Mieux : donner ce rôle à un Custom Model Binder !
public class GuidModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
Guid IdParse = Guid.Empty;
if (bindingContext.ValueProvider.GetValue("id") != null)
Guid.TryParse(bindingContext.ValueProvider.GetValue("id").AttemptedValue, out IdParse);
return IdParse;
}
}Il implémente IModelBinder, interface n’exposant qu’une fonctionnalité : BindModel. Bon là j’ai fait un truc un peu crade quand même parce que je débute en tuto, mais l’idée est de rendre complètement transparente la transcription des formats de données renvoyées par la vue au contrôleur et inversement.
Ainsi, notre action PostGuid deviendra :
public class RefreshItController : Controller
{
public ActionResult Index()
{
GuidModel model = new GuidModel {Guid = Guid.NewGuid()};
return View(model);
}
public ActionResult PostGuid([ModelBinder(typeof(GuidModelBinder))] Guid inputGuid)
{
FaireQuelqueChoseAvec(inputGuid);
return Json(new { message="Le Custom Model Binding C'est Drolement Chouette !"});
}
private void FaireQuelqueChoseAvec(Guid inputGuid)
{
return;
}
}Le paramétrage de l’action change (un peu brutal d’ailleurs) mais j’imagine qu’on peut rendre ça encore plus clean avec des filtres… Enfin l’idée est là en tout cas !
Plutôt cool non ?
Pour information je répète : cet exemple est inutile en l’état car Asp.net MVC sait faire tout seul la conversion string -> Guid en paramètre d’une action, sans qu’il y ait besoin d’un binder customisé. Je l’ai personnellement plutôt utilisé pour caster des listes ou des objets complexes.
D’autres utilisations des Custom Model Binders sont possibles, notemment (surtout?) la validation des données mais j’estime personnellement qu’il devrait y avoir autant de couches de validations que de couches applicatives successives (un peu comme dans la philosophie du modèle OSI), ce qui à mon sens ne restreint pas les Model Binders à telle ou telle tâche spécifique.
En conclusion, je vois les Custom Model Binders comme un container applicatif de premier niveau permettant d’effectuer des tâches à tendance « ingrates ».
Voilà voilà ! N’hésitez pas à me faire des retours dans les commentaires si ce que j’ai écrit n’est pas exact ou si j’ai oublié des choses importantes.
A+
Rescue Time
by F5 on nov.07, 2011, under Prog
Si comme moi vous faites partie des gens dont le cerveau n’est pas capable de réguler ses élans de fénéantise, cet outil pourrait s’avérer utile.
Il s’agit d’un petit démon à installer sur votre machine (Mac, Linux ou Windows) qui scanne votre activité en permanence : les applications se trouvant au premier plan, et s’il s’agit d’un navigateur les sites que vous visitez. Rescue Time compile toutes ces données pour vous les ressortir sous forme de graphique, avec une note comparée à celle de la moyenne des utilisateurs de l’application.
Sur le même écran, vous avez accès à vos stats en terme de productivité. Soit flippantes soit rassurantes, les courbes que vous voyez décrivant votre activité sont colorées et faciles à comprendre.

Elles sont paramétrables par périodes (jour, semaine, mois, année) et il est possible pour chaque activité scannée par Rescue Time de lui spécifier un indice de productivité (de ‘-2′, très improductif, à ‘+2′, très productif).
L’ennui c’est le coté ‘En ligne’ de l’outil qui laisse imaginer ce genre de données sur des serveurs distants… Mais avec Twitter et Facebook on n’est plus à ça près, si ?
Bref, super application anti-procrastination qui, si elle ne vous fera pas forcément travailler plus, vous aidera à voir les vrais temps d’inactivité qu’on passe notre temps à minimiser auprès de la hiérarchie
C’est par ici pour tester.
