2012-05-29 31 views
5

He echado un vistazo a otras preguntas y respuestas en este sitio, pero no puedo encontrar la respuesta que necesito.Cómo pasar un modelo que contiene un modelo IEnumerable (complejo) a un controlador desde una vista C# MVC3?

que tienen una entidad StudentRecord:

public class StudentRecord : Persistent { 
     public virtual string LastName { get; set; } 
     public virtual string FirstName { get; set; } 
     public virtual DateTime Dob { get; set; } 
     public virtual int StudentRef { get; set; } 
     public virtual IEnumerable<StudentAddress> Addresses { get; set; } 
     public virtual StudentAddress Address { get; set; } 
     public virtual string Notes { get; set; } 
    } 

Como se puede ver que contiene una sola entidad StudentAddress y también un IEnumerable de StudentAddress:

public class StudentAddress: Persistent { 
     public virtual int StudentRef { get; set; } 
     public virtual string Addressee { get; set; } 
     public virtual string Property { get; set; } 
     public virtual string District { get; set; } 
     public virtual string PostalTown { get; set; } 
     public virtual string County { get; set; } 
     public virtual string Postcode { get; set; } 
    } 

estoy pasando el expediente de un estudiante a una vista , contenido dentro de un modelo de vista:

public class UserViewModel { 
     public StudentRecord Student;  
     public ICurrentUserService CurrentUserService; 
     public ParentUser ParentUser;   
    } 

Luego, mostrarlo en un formulario por lo que t puede editarse y enviar el formulario pasa el StudentRecord de nuevo al controlador. Todo funciona bien, excepto que las direcciones dentro de StudentRecord son nulas. El único StudentAddress en el StudentRecord es para si se agrega una nueva dirección, y eso funciona bien también.

¿Es posible editar y enviar las direcciones de vuelta al controlador, o debo tenerlas en un formulario separado en una página separada? Puedo hacer eso, pero preferiría tenerlo todo en uno.

Mi problema puede ser que no es posible, o puede ser la forma en que estoy poniendo las direcciones en el formulario. Un estudiante puede tener más de una dirección.

Aquí es la forma: (He despojado a cabo algún diseño HTML para mayor claridad 'agregar otra dirección' Tickbox muestra la sección Dirección de Nuevos Estudiantes con jQuery..)

@using (Html.BeginForm()) { 
    Personal Details 
    Full Name: @Html.TextBoxFor(x => x.Student.FirstName) @Html.TextBoxFor(x => x.Student.LastName) 
    DOB: @Html.TextBoxFor(x => x.Student.Dob) 

    @if (Model.Student.Addresses.Any()) { 
     // Only print addresses if they exist 
      int count = 1; 
      int element = 0; 
       @if (Model.Student.Addresses.Count() > 1) { 
        foreach (var address in Model.Student.Addresses) { 
         Student Address @count 
         Addressee @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).Addressee) 
         Property @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).Property) 
         District @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).District) 
         Postal Town @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).PostalTown) 
         County @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).County) 
         Postcode @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).Postcode) 
         count++; 
         element++; 
        } //end foreach 
       } else { 
        Student Address 
        Addressee @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).Addressee) 
        Property @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).Property) 
        District @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).District) 
        Postal Town @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).PostalTown) 
        County @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).County) 
        Postcode @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).Postcode) 
       } @*end if (Model.Student.Addresses.Count() > 1)*@ 

       Add another address @Html.CheckBox("Add another address", false, new {@id = "newBox"}) 

       New Student Address 
       Addressee @Html.TextBoxFor(x => x.Student.Address.Addressee) 
       Property @Html.TextBoxFor(x => x.Student.Address.Property) 
       District @Html.TextBoxFor(x => x.Student.Address.District) 
       Postal Town @Html.TextBoxFor(x => x.Student.Address.PostalTown) 
       County @Html.TextBoxFor(x => x.Student.Address.County) 
       Postcode @Html.TextBoxFor(x => x.Student.Address.Postcode) 
    } else { 
     No address for this student. 
    } @*end if (Model.Student.Addresses.Any())*@ 

    Notes: @Html.TextAreaFor(x => x.Student.Notes, new { @style = "width: 100%;"}) 

    <input type="submit" value="Send" class="btn btn-primary" style="clear: both;"/> 
} @*end of form*@ 

Respuesta

8

El problema es que el name los atributos de los controles de entrada de texto no contienen valores correctos. Los invito a leer el following blog post para comprender mejor la convención utilizada por el encuadernador de modelos predeterminado para enlazar a colecciones y diccionarios.

entonces recomendaría que el uso de plantillas de edición en lugar de escribir foreach en sus puntos de vista:

@using (Html.BeginForm()) { 
    Personal Details 

    @Html.LabelFor(x => x.Student.FirstName, "Full Name:") 
    @Html.EditorFor(x => x.Student.FirstName) 
    @Html.EditorFor(x => x.Student.LastName) 

    @Html.LabelFor(x => x.Student.Dob, "DOB:") 
    @Html.TextBoxFor(x => x.Student.Dob) 

    @if (Model.Student.Addresses.Any()) { 
     @Html.EditorFor(x => x.Student.Addresses) 
    } else { 
     <text>No address for this student.</text> 
    } 

    @Html.LabelFor(x => x.Student.Notes, "Notes:") 
    @Html.TextAreaFor(x => x.Student.Notes, new { @style = "width: 100%;"}) 

    <input type="submit" value="Send" class="btn btn-primary" style="clear: both;"/> 
} 

y luego definir un editor de plantillas a medida que se vuelve automáticamente para cada elemento de la colección de direcciones (~/Views/Shared/EditorTemplates/StudentAddress.cshtml) :

@model StudentAddress 
@Html.LabelFor(x => x.Addressee, "Addressee") 
@Html.EditorFor(x => x.Addressee) 

@Html.LabelFor(x => x.Property, "Property") 
@Html.EditorFor(x => x.Property) 

@Html.LabelFor(x => x.District, "District") 
@Html.EditorFor(x => x.District) 

@Html.LabelFor(x => x.PostalTown, "Postal Town") 
@Html.EditorFor(x => x.PostalTown) 

@Html.LabelFor(x => x.County, "County") 
@Html.EditorFor(x => x.County) 

@Html.LabelFor(x => x.Postcode, "Postcode") 
@Html.EditorFor(x => x.Postcode) 

Pero todo esto es estático. Si desea poder agregar y eliminar direcciones dinámicamente, lo invito a leer el following blog post de Steven Sanderson en el que ilustra cómo se podría usar un helper HTML personalizado para generar nombres propios para los campos de entrada (Html.BeginCollectionItem) y usar AJAX para agregar nuevas filas

+0

Gracias por su rápida respuesta. Voy a intentar esto y echar un vistazo a su tema de lectura sugerido. Publicaré mis resultados aquí. Muchas gracias. – tekiegirl

+0

Gracias, esto funcionó perfectamente. Examinaré dinámicamente las direcciones también. – tekiegirl

Cuestiones relacionadas