Come funziona MVC 4 List Model Binding?

Se voglio un insieme di input in un modulo per associare a un List in MVC 4, so che la seguente convenzione di denominazione per gli attributi del name input funzionerà:

    

Ma sono curioso di sapere come perdonare il modello di rilegatura. Ad esempio, che dire di quanto segue:

    

In che modo il raccoglitore modello può gestirlo? Legherebbe ad un List di lunghezza 9 con valori null? O sarebbe ancora associato a un List di lunghezza 3? O potrebbe soffocare del tutto?

Perché mi importa

Voglio implementare un modulo dinamico in cui l’utente può aggiungere righe al modulo e anche eliminare righe dal modulo. Quindi se un utente cancella la riga 2 su 8 righe totali, voglio sapere se ho bisogno di rinumerare tutti gli input successivi.

Esiste un formato di filo specifico da utilizzare con le raccolte. Questo è discusso sul blog di Scott Hanselman qui:

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

Un altro post sul blog di Phil Haack parla di questo qui:

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Infine, un post di blog che fa esattamente ciò che vuoi qui:

http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

Ho seguito questo approccio collegato nei blog sopra e ho aggiunto alcuni dettagli che potrebbero essere utili ad alcuni – specialmente perché volevo aggiungere dynamicmente un numero qualsiasi di righe ma non volevo usare AJAX per farlo (volevo che il modulo inviasse solo nella posta). Inoltre, non volevo preoccuparmi di mantenere ID sequenziali. Stavo catturando un elenco di date di inizio e fine:

Visualizza modello:

 public class WhenViewModel : BaseViewModel { public List Dates { get; set; } //... Other properties } 

Inizio / Fine Data Visualizza Modello:

 public class DateViewModel { public string DateID { get; set; } public DateTime? StartDate { get; set; } public DateTime? EndDate { get; set; } } 

Quindi usandoli nella pagina (con datepicker):

 
@{ foreach (DateViewModel d in Model.Dates) { @:
@Html.Hidden("Dates.Index", d.DateID) @Html.Hidden("Dates[" + d.DateID + "].DateID", d.DateID) //ID again to populate the view model @Html.TextBox("Dates[" + d.DateID + "].StartDate", d.StartDate.Value.ToString("yyyy-MM-dd")) @:
@:
@Html.TextBox("Dates[" + d.DateID + "].EndDate", d.EndDate.Value.ToString("yyyy-MM-dd")) @:
} }
Add Dates

Poiché il post del blog è collegato nel post @ErikTheVikings sopra descritto, la raccolta viene creata dall’elemento nascosto ripetuto: @Html.Hidden("Dates.Index", d.DateID) per ogni voce nella raccolta sulla pagina.

Volevo aggiungere arbitrariamente delle righe senza utilizzare AJAX per inviare dati al server, cosa che ho fatto creando un div nascosto contenente un modello di una “riga” / elemento nella raccolta:

Riga “Template” nascosta:

  

Quindi usa jQuery che clona il modello, fornisce un ID casuale da usare per una nuova riga e aggiunge la riga clonata ora visibile al div contenente sopra:

jQuery per completare il processo:

  

Esempio JSFiddle del risultato: http://jsfiddle.net/mdares/7JZh4/

Ho una lista dynamic che assomiglia a questo:

 
  • --//--

quindi quando aggiungo o rimuovo la riga (elemento li) devo riordinare gli elementi

  this.reorderItems = function () { var li = this.el_list.find('li'); for (var i = 0; i < li.length; i++) { var inputs = $(li[i]).find('input'); $.each(inputs, function () { var input = $(this); var name = input.attr('name'); input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + i + ']')); var id = input.attr('id'); input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + i + '__')); }); } }; 

questa lista è stata inserita in semplice Html.BeginFrom dal client e come List nel parametro action su serveride

Ho anche affrontato problemi simili in passato, e uso KnockoutJS per gestire questo scenario.

Fondamentalmente, Knockout invia la raccolta in una stringa JSON e li ho deserializzati nel mio controller.

Per maggiori informazioni: http://learn.knockoutjs.com/#/?tutorial=collections

Ho riscontrato un piccolo problema quando utilizzo Chrome Browser e faccio clic sul pulsante Indietro, e trovo l’input con type = “hidden” quando i valori impostati dynamicmente non sono stati gestiti correttamente dal browser Chrome.

forse possiamo cambiare

  

a

 

Ulteriori informazioni: Chrome non memorizza nella cache i valori del campo modulo nascosto per l’utilizzo nella cronologia del browser http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/