Laurent Kempé
Utilisation du CustomModelBinderAttribute d’ASP.NET MVC
Comment utiliser le CustomModelBinderAttribute d’ASP.NET MVC pour lire des valeurs des headers de requêtes HTTP
Par Laurent Kempé publié le 24/09/2010 à 17:15, lu 2620 fois,
Jusqu’à la semaine dernière j’étais persuadé que le DefaultModelBinder d’ASP.NET MVC était capable de chercher des valeurs dans les headers des requêtes http. Après avoir écrit un exemple simple de contrôleur je me suis vite rendu compte que cela ne marchait pas.
Quelques recherches sur le web plus tard, rien, puis après une discussion avec Jon et le parcours des sources d’ASP.NET MVC on se rend compte les deux que ce que nous pensions était faux.
Le DefaultModelBinder d’ASP.NET MVC ne va pas chercher de valeur dans les headers des requêtes http.
En cherchant un peu plus loin je trouve le CustomModelBinderAttribute

namespace System.Web.Mvc

{

    [AttributeUsage(

        AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Parameter |

        AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]

    public abstract class CustomModelBinderAttribute : Attribute

    {

        public abstract IModelBinder GetBinder();

    }

}

 

Une classe abstraite, à étendre donc qui semble bien prometteuse. Son unique méthode GetBinder() retourne un IModelBinder.
Il s’agit donc d’un attribut que l’on va pouvoir ajouter devant un paramètre afin qu’ASP.NET MVC puisse faire correctement le binding vers le Model depuis ce que l’on veut, dans notre cas une valeur stockée dans le header http.
Par exemple

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Publish([HttpHeaderModelBinder]string myValue)

{

    ...

}

 

Avec le CustomModelBinderAttribute qui ressemble à cela

public class HttpHeaderModelBinderAttribute : System.Web.Mvc.CustomModelBinderAttribute

{

    public override IModelBinder GetBinder()

    {

        return new HttpHeaderBinder();

    }

}

 

Et enfin nous pouvons écrire le ModelBinder

public class HttpHeaderBinder : DefaultModelBinder

{

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)

    {

        return controllerContext.HttpContext.Request.Headers.Get("MyValue");

    }

}

 

Mais quel avantage à faire tout cela ?
Cela semble beaucoup de code pour juste aller lire une valeur depuis le header http, alors que nous aurions pu la lire directement dans notre contrôleur.
Le souci si nous lisions cette valeur directement dans notre contrôleur c’est que nous créerions une dépendance entre notre contrôleur et le HttpContext et notre contrôleur serait de suite plus difficile à unit tester car il nous faudrait un mock du HttpContext.
De cette façon notre méthode ne dépend plus du HttpContext, ce qui la rend beaucoup plus facilement testable par unit test.
 
» Démarrer une discussion