2012-05-29 7 views
5

Ho dato un'occhiata ad altre domande e risposte su questo sito ma non riesco a trovare la risposta di cui ho bisogno.Come passare un modello contenente un modello IEnumerable (complesso) in un controller da una vista C# MVC3?

devo un'entità 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; } 
    } 

Come si può vedere che contiene una singola entità StudentAddress e anche un IEnumerable di 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; } 
    } 

sto passando un record studente di una vista , contenute all'interno di un ViewModel:

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

Poi la visualizzazione in una forma così ho t può essere modificato e l'invio del modulo passa di nuovo al Regolatore. Tutto funziona bene, tranne che gli indirizzi all'interno dello StudentRecord sono nulli. Il singolo StudentAddress nello StudentRecord serve se viene aggiunto un nuovo indirizzo, e che funziona anche bene.

È possibile modificare e inviare gli indirizzi al controller oppure è necessario averli in un modulo separato in una pagina separata? Posso farlo ma preferirei avere tutto in uno.

Il mio problema potrebbe essere che non è possibile o potrebbe essere il modo in cui inserisco gli indirizzi nel modulo. Uno studente può avere più di un indirizzo.

Qui è la forma: (io ho messo a nudo alcuni layout HTML per chiarezza Il 'Aggiungi un altro indirizzo' tickbox mostra la sezione Nuovo indirizzo per studenti 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*@ 

risposta

8

Il problema è che il name gli attributi dei controlli di input del testo non contengono valori corretti. Vi invito a leggere lo following blog post per capire meglio la convenzione utilizzata dal modello di default del binder per collegarsi a raccolte e dizionari.

Poi ti consiglierei di utilizzare Editor modelli invece di scrivere loop foreach nel vostro punto di 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;"/> 
} 

e quindi definire un editor di modelli personalizzati che verranno resi automaticamente per ogni elemento della collezione Indirizzi (~/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) 

Ma tutto questo è statico. Se vuoi essere in grado di aggiungere e rimuovere gli indirizzi in modo dinamico, ti invito a leggere lo following blog post di Steven Sanderson in cui illustra come utilizzare un helper HTML personalizzato per generare nomi appropriati per i campi di input (Html.BeginCollectionItem) e utilizzare AJAX per aggiungere nuove righe.

+0

Grazie per la rapida risposta. Farò una prova e dare un'occhiata al tuo argomento di lettura suggerito. Pubblicherò i miei risultati qui. Grazie molto. – tekiegirl

+0

Grazie, ha funzionato perfettamente. Cercherò anche di aggiungere gli indirizzi in modo dinamico. – tekiegirl

Problemi correlati