Frage

Ich bin ein paar eigenen Bindemittel für komplexe Typen in meinem Modell zu schaffen. Mein Modell besteht aus Objekten zusammengesetzt, die jeweils eine eigene Bindemittel haben. Ich möchte das Basisobjekt seine schmutzige Arbeit zu tun und dann das komplexe Objekt füllen Sie es, indem man aus dem Standard-Routing-Modelbinder kapselt. Wie kann ich das tun?

Zur Veranschaulichung habe ich ein sehr einfaches Beispiel erstellt.

Sprich mein Modell dieser Objekte enthält.

public class Person
{
    public string Name {get; set;}
    public PhoneNumber PhoneNumber {get; set;}
}

public class PhoneNumber
{
    public string AreaCode {get; set;}
    public string LocalNumber {get; set;}
}

Und ich habe die folgenden Bindemittel für jedes dieser Modelle. Nicht, dass der PersonBinder die Phone zu füllen braucht aber will nicht den Code in dem Phone Bindemittel duplizieren. Wie funktioniert delegieren sie an die stardard Binder Routing?

zu unterstützen
public class PersonBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext     bindingContext)
    {
        Person person = new Person();
        person.Name = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "Name")).AttemptedValue

        // This is where I'd like to have the PhoneNumber object use binding from another customer ModelBinder.
        // Of course the bindingContext.ModelName should be updated to its current value + "PhoneNumber"
        person.PhoneNumber = ???;  // I don't want to explicitly call the PhoneNumberBinder it should go through standard Binding routing.  (ie.  ModelBinders.Binders[typeof(PhoneNumber)] = new PhoneNumberBinder();)

        return person;       
    }
}

public class PhoneNumberBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext     bindingContext)
    {
        PhoneNumber phoneNumber = new PhoneNumber();
        phoneNumber.AreaCode = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "AreaCode")).AttemptedValue
        phoneNumber.LocalNumber = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "LocalNumber")).AttemptedValue

        return phoneNumber;
    }
}

Und natürlich habe ich meine Modelbinders in der Global.asax.cs Datei registriert.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterRoutes(RouteTable.Routes);

    ModelBinders.Binders[typeof(Person)] = new PersonBinder();
    ModelBinders.Binders[typeof(PhoneNumber)] = new PhoneNumberBinder();
}

Danke,

Justin

War es hilfreich?

Lösung

Nun ich es geschafft, mit einer Lösung zu kommen. Bitte fühlen Sie sich frei zu kommentieren ihre Gültigkeit.

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
     Person person = new Person();
     person.Name = bindingContext.ValueProvider.GetValue("Name").AttemptedValue

     if (bindingContext.ModelName == String.Empty)
     {
         bindingContext.ModelName = "PhoneNumber";
     }
     else
     {
         bindingContext.ModelName = bindingContext.ModelName + ".PhoneNumber";
     }

     PhoneNumber phoneNumber = new PhoneNumber();
     bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => phoneNumber, phoneNumber.GetType());

     IModelBinder binder = ModelBinders.Binders[typeof(PhoneNumber)];
     if (binder == null)
     {
          binder = ModelBinders.Binders.DefaultBinder;
     }

     person.PhoneNumber = binder.BindModel(controllerContext, bindingContext) as PhoneNumber;

     return person;                         
}

Hier ist eine Zusammenfassung dessen, was ich getan habe.

  1. Nachschlagen der Modelbinder der global zugängliche ModelBinders.Binders Sammlung mit (Rückfall auf den Standard, wenn man nicht registriert ist)
  2. Erstellen Sie die ModelMetadataProvider für das Modell ich verbindlich.
  3. Stellen Sie die Modelname-Eigenschaft des Binding zum Modell Eigenschaft ich bevölkern bin versucht ( „Phone“).

Andere Tipps

Anstatt Schreib ein Bindemittel Sie Benutzer AutoMapper können und die komplexe Modellkonstruktion in der Aktion behandeln.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top