Sie sind hier: Weblog

Benutzerdefinierte ModelBinder für ASP.NET MVC

Foto ,
18.01.2013 01:00:00

ModelBinder ermitteln jene Werte, die ASP.NET MVC zu den Übergabeparametern von Action-Methoden zweist. Der Standardimplementierung des Model-Binders ist es zum Beispiel zu verdanken, dass bei einem Aufruf der Url /hotel/find?minSterne=3 der Wert 3 an den Parameter minSterne der angestoßenen Action-Methode zugewiesen wird. Bei Model-Binder handelt es sich um Implementierungen des Interfaces System.Web.Mvc.IModelBinder.
Die Standardimplementierung des Model-Binders trägt den Namen DefaultModelBinder. Möchte man die Standard-Logik lediglich erweitern, bietet es sich an, von dieser Klasse abzuleiten anstatt IModelBinder komplett neu zu implementieren. Das Ergebnis eines solchen Vorhabens findet sich in Form der Klasse SimpleCustomModelBinder im nachfolgenden Listing. Diese Klasse erbt von DefaultModelBinder und überschreibt die Methode BindModel. Diese Methode erhält von ASP.NET MVC zwei Parameter, aus denen hervor geht, welcher Wert zu binden ist. Hierbei ist zu beachten, dass Framework-intern der Begriff Model auch für Parameter sowie Teile von Models Verwendung findet.
Die betrachtete Methode informiert durch Einsatz der Eigenschaft ModelName der übergebenen BindingContext-Instanz über den Namen des zu bindenden Parameters; über ModelType bringt sie den Typ dieser Eigenschaft in Erfahrung. Handelt es sich um einen Parameter userName vom Typ string, returniert sie den Namen der Identität des aktuellen Principal-Objektes, welches unter .NET per Definition Informationen über den aktuellen Benutzer beinhaltet. Dies veranlasst ASP.NET MVC dazu, den retournierten Namen an den jeweiligen Parameter zuzuweisen.
Handelt es sich hingegen um einen Parameter vom Typ IPrincipal, liefert BindModel den aktuellen Principal. In allen anderen Fällen, verwendet die betrachtete Methode die Logik der Standardimplementierung, indem sie unter Verwendung des Schlüsselworts base an diese weiterdelegiert.
public class SimpleCustomModelBinder: DefaultModelBinder {

    public override object BindModel(
                   ControllerContext controllerContext, 
                   ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelName == "userName" && 
                               bindingContext.ModelType == typeof(string))
        {
            return Thread.CurrentPrincipal.Identity.Name;
        }

        if (bindingContext.ModelType == typeof(IPrincipal))
        {
            return Thread.CurrentPrincipal;
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}
Zum Registrieren benutzerdefinierter Model-Binder stehen mehrere Möglichkeiten zur Verfügung. Möchte der Entwickler, dass ein Model-Binder nur für ausgewählte Parameter zum Einsatz kommt, kann er diese mit dem Attribut ModelBinder annotieren und im Zuge dessen den Typ des gewünschten Model-Binders angeben. Im nachfolgenden Beispiel definiert der Entwickler auf diese Weise, dass ASP.NET MVC für das Binden des Parameters ary der Action-Methode Stuff den benutzerdefinierte IntArrayModelBinder heranzuziehen hat.
public ActionResult Stuff(
     [ModelBinder(typeof(IntArrayModelBinder))] int[] ary)  { … }
Um anzugeben, dass ASP.NET MVC einen Model-Binder generell zum Binden eines bestimmten Datentyps verwenden soll, verwendet der Entwickler die Konfigurations-Methode ModelBinders.Binders.Add, an welche er sowohl den Typ als auch den gewünschten Model-Binder übergibt:
ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());
Da Konfigurationseinstellungen beim Start der Web-Anwendung bekannt gegeben werden sollten, bietet es sich an, diese Methode innerhalb der Methode Application_Start, welche sich in der Klasse MvcApplication in der Datei global.asax befindet, aufzurufen.
In Fällen, in denen der Entwickler weder auf der Ebene der Action-Methode noch auf der Ebene des Typs einen Model-Binder registriert hat, stützt sich ASP.NET MVC auf einen registrierten Standard-Model-Binder. Der Entwickler kann über die Eigenschaft ModelBinders.Binders.DefaultBinder angeben, welche Implementierung als Standard-Model-Binder fungieren soll:
ModelBinders.Binders.DefaultBinder = new SimpleCustomModelBinder();
Macht er dies nicht, verweist diese Eigenschaft auf die Standard-Implementierung DefaultModelBinder.