net mvc editar asp c# .net asp.net-mvc asp.net-mvc-4 model-binding

c# - editar - ¿Cómo funciona MVC 4 List Model Binding?



model binding mvc 5 (5)

Si quiero un conjunto de entradas en una forma para enlazar a una List en MVC 4, sé que la siguiente convención de nomenclatura para atributos de name input funcionará:

<input name="[0].Id" type="text" /> <input name="[1].Id" type="text" /> <input name="[2].Id" type="text" />

Pero tengo curiosidad acerca de cuán indulgente es el aglutinante modelo. Por ejemplo, ¿qué pasa con lo siguiente?

<input name="[0].Id" type="text" /> <input name="[3].Id" type="text" /> <input name="[8].Id" type="text" />

¿Cómo manejaría esto la carpeta modelo? ¿Se uniría a una List de longitud 9 con nulos? ¿O aún se uniría a una List de longitud 3? ¿O se ahogaría por completo?

Por qué me importa

Quiero implementar un formulario dinámico en el que el usuario pueda agregar filas al formulario y también eliminar filas del formulario. Entonces, si un usuario elimina la fila 2 de las 8 filas totales, quiero saber si tendré que volver a numerar todas las entradas posteriores.


Hay un formato de cable específico para usar con colecciones. Esto se discute en el blog de Scott Hanselman aquí:

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

Otra entrada de blog de Phil Haack habla de esto aquí:

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

Finalmente, una entrada de blog que hace exactamente lo que quiere aquí:

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


Seguí este enfoque vinculado en los blogs anteriores y agregué algunos detalles que podrían ser útiles para algunos, especialmente porque quería agregar dinámicamente cualquier cantidad de filas pero no quería usar AJAX para hacerlo (quería que el formulario solo se enviara). en el post). Tampoco quería preocuparme por mantener identificadores secuenciales. Estaba capturando una lista de fechas de inicio y finalización:

Ver modelo:

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

Modelo de vista de fecha de inicio / finalización:

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

Luego utilizándolos en la página (con datepicker):

<div class="grid-8-12 clear" id="DatesBlock"> @{ foreach (DateViewModel d in Model.Dates) { @:<div class="grid-5-12 left clear"> @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")) @:</div> @:<div class="grid-5-12"> @Html.TextBox("Dates[" + d.DateID + "].EndDate", d.EndDate.Value.ToString("yyyy-MM-dd")) @:</div> <script type="text/javascript"> $(''input[name="Dates[@d.DateID].StartDate"]'') .datepicker({ dateFormat: ''yy-mm-dd''}); $(''input[name="Dates[@d.DateID].EndDate"]'') .datepicker({dateFormat: ''yy-mm-dd''}); </script> } } </div> <a href="#" onclick="AddDatesRow()">Add Dates</a>

Como se describe en la publicación del blog vinculada en la publicación de @ErikTheVikings, la colección se crea mediante el elemento oculto repetido: @Html.Hidden("Dates.Index", d.DateID) para cada entrada de la colección en la página.

Quería agregar filas arbitrariamente sin usar AJAX para publicar datos en el servidor, lo cual hice creando un div oculto que contiene una plantilla de una "fila" / elemento en la colección:

Fila oculta de "Plantilla":

<div id="RowTemplate" style="display: none"> <div class="grid-5-12 clear"> @Html.Hidden("Dates.Index", "REPLACE_ID") @Html.Hidden("Dates[REPLACE_ID].DateID", "REPLACE_ID") @Html.TextBox("Dates[REPLACE_ID].StartDate", "") </div> <div class="grid-5-12"> @Html.TextBox("Dates[REPLACE_ID].EndDate", "") </div> </div>

Luego, se utilizó jQuery, que clona la plantilla, proporciona una identificación aleatoria para usar en una nueva fila y agrega la fila clonada ahora visible al div que contiene a continuación:

jQuery para completar el proceso:

<script type="text/javascript"> function AddDatesRow() { var tempIndex = Math.random().toString(36).substr(2, 5); var template = $(''#RowTemplate''); var insertRow = template.clone(false); insertRow.find(''input'').each(function(){ //Run replace on each input this.id = this.id.replace(''REPLACE_ID'', tempIndex); this.name = this.name.replace(''REPLACE_ID'', tempIndex); this.value = this.value.replace(''REPLACE_ID'', tempIndex); }); insertRow.show(); $(''#DatesBlock'').append(insertRow.contents()); //Attach datepicker to new elements $(''input[name="Dates[''+tempIndex+''].StartDate"]'') .datepicker({dateFormat: ''yy-mm-dd'' }); $(''input[name="Dates[''+tempIndex+''].EndDate"]'') .datepicker({dateFormat: ''yy-mm-dd'' }); } </script>

Ejemplo JSFiddle del resultado: http://jsfiddle.net/mdares/7JZh4/


También me enfrento a un problema similar en el pasado, y utilizo KnockoutJS para manejar dicho escenario.

Básicamente, Knockout envía la colección en una cadena JSON, y los deserialicé en mi controlador.

Para más información: http://learn.knockoutjs.com/#/?tutorial=collections


Tengo un pequeño problema cuando uso Chrome Browser y hago clic en el botón Atrás, y encuentro la entrada con type = "hidden" cuando los valores establecidos dinámicamente no fueron manejados correctamente por Chrome Browser.

tal vez podamos cambiar

<input type="hidden" name="Detes.Index" value="2016/01/06" />

a

<div style="display: none"> <input type="text" name="Detes.Index" value="2016/01/06" /> </div>

Más información: Chrome no almacena valores de campo de formulario ocultos para su uso en el historial del navegador http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/


Tengo una lista dinámica que se ve así:

<ul id="okvedList" class="unstyled span8 editableList"> <li> <input data-val="true" data-val-required="The Guid field is required." id="Okveds_0__Guid" name="Okveds[0].Guid" type="hidden" value="2627d99a-1fcd-438e-8109-5705dd0ac7bb"> --//-- </li>

entonces cuando agrego o quito la fila (elemento li) tengo que reordenar los artículos

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 + ''__'')); }); } };

esta lista se coloca en Html.BeginFrom simple desde el lado del cliente y como Lista en el parámetro de acción en el lado del servidor