2009-02-27 8 views
12

Estoy queriendo obtener un trabajo vinculante en mi aplicación mvc. Encuentro que las propiedades anidadas no están automáticamente vinculadas por la carpeta de modelo predeterminada en la versión RC1 de asp.net mvc. Tengo la siguiente estructura de clases:Encuadernación de modelo de propiedades anidadas en asp.net mvc

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

Dónde Name se define como:

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

Mi vista se define a lo largo de las líneas de:

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"); 
} 

Mi acción del controlador se define como:

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 propiedad Email está vinculada correctamente, pero no las propiedades Name.Forename o Name.Surname. ¿Alguien puede decir si esto debería funcionar usando el archivador de modelo predeterminado y estoy haciendo algo mal o si no funciona y tengo que rodar mi propio código para enlazar propiedades anidadas en objetos de modelo?

Respuesta

9

Creo que el problema se debe al prefijo Name en las propiedades. Creo que deberás actualizarlo como dos modelos y especificar el prefijo para el segundo. Tenga en cuenta que eliminé el FormCollection de los parámetros y usé la firma UpdateModel que depende del proveedor de valores integrado y especifica una lista blanca de propiedades a considerar.

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

Esto funciona genial, gracias tvanfosson. –

+0

SingleOrDefault se puede llamar directamente con una expresión lamda –

+0

@PhilippM tienes toda la razón, ¡actualizado! – tvanfosson

4

Eso es muy interesante porque si hubiera hecho

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

estoy usando esto con gran éxito. Supongo que entonces podrías sincronizar los dos objetos de contacto juntos.

Hubiera pensado que el UpdateModel y el enlace al parámetro utilizan la misma llamada detrás de escena. nota: no he intentado reproducir su problema.

3

Para enlazar un nombre en lugar del modelo de vista completa en la POST es para indicar al archivador modelo que se usará un prefijo. Esto se hace usando BindAttribute.

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