2009-02-27 27 views
12

Sto cercando di ottenere un po 'di lavoro vincolante nella mia applicazione mvc. Trovo che le proprietà nidificate non vengano automaticamente associate dal raccoglitore modello predefinito nella versione RC1 di asp.net mvc. Ho la seguente struttura di classe:Associazione del modello di proprietà nidificate in asp.net mvc

public class Contact{ 
    public int Id { get; set; } 
    public Name Name { get; set; } 
    public string Email { get; set; } 
} 

Dove Name è definito come:

public class Name{ 
    public string Forename { get; set; } 
    public string Surname { get; set; } 
} 

mio visualizzazione è definita lungo le linee di:

using(Html.BeginForm()){ 
    Html.Textbox("Name.Forename", Model.Name.Forename); 
    Html.Textbox("Name.Surname", Model.Name.Surname); 
    Html.Textbox("Email", Model.Email); 
    Html.SubmitButton("save", "Save"); 
} 

è definita mia azione controller come:

public ActionResult Save(int id, FormCollection submittedValues){ 
    Contact contact = get contact from database; 
    UpdateModel(contact, submittedValues.ToValueProvider()); 

    //at this point the Name property has not been successfully populated using the default model binder!!! 
} 

La proprietà Email è vincolata correttamente ma non le proprietà Name.Forename o Name.Surname. Qualcuno può dire se questo dovrebbe funzionare usando il modello predefinito di default e sto facendo qualcosa di sbagliato o se non funziona e ho bisogno di rollare il mio codice per legare le proprietà annidate sugli oggetti del modello?

risposta

9

Penso che il problema sia dovuto al prefisso del nome sulle proprietà. Penso che dovrai aggiornarlo come due modelli e specificare il prefisso per il secondo. Si noti che ho rimosso il FormCollection dai parametri e ho utilizzato la firma di UpdateModel che si basa sul provider di valori incorporato e specifica una lista bianca di proprietà da considerare.

public ActionResult Save(int id) 
{ 
    Contact contact = db.Contacts.SingleOrDefault(c => c.Id == id); 

    UpdateModel(contact, new string[] { "Email" }); 
    string[] whitelist = new string[] { "Forename", "Surname" }; 
    UpdateModel(contact.Name, "Name", whitelist); 
} 
+0

Questo funziona benissimo, grazie tvanfosson. –

+0

SingleOrDefault può essere chiamato direttamente con un'espressione lamda –

+0

@PhilippM hai assolutamente ragione, aggiornato! – tvanfosson

4

Questo è molto interessante, perché se si fosse realizzato

public ActionResult Save(int id, Contact contact) 
{ 
    //contact here would contain the nested values. 
} 

Sto usando questo con grande successo. Suppongo quindi che potresti in qualche modo sincronizzare i due oggetti Contatto insieme.

Avrei pensato che UpdateModel e il binding al parametro utilizzano la stessa chiamata dietro le quinte. nota: non ho provato a riprodurre il problema.

3

Per associare un nome anziché l'intero modello di vista su POST è necessario indicare al raccoglitore modello che verrà utilizzato un prefisso. Questo viene fatto usando BindAttribute.

public ActionResult AddComment([Bind(Prefix = "Name")] Name name) 
{ 
    //do something 
} 
Problemi correlati