asp.net mvc 3 - tutorial - El enlace MVC al modelo con propiedad de lista ignora otras propiedades
mvc c# windows forms (3)
Tengo un ViewModel básico con una propiedad que es una lista de tipos complejos. Al enlazar, parece que me quedo estancado al obtener la lista de valores O las otras propiedades del modelo dependiendo de los valores publicados (es decir, la disposición de la vista).
El modelo de vista:
public class MyViewModel
{
public int Id { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public List<MyDataItem> Data { get; set; }
}
public class MyDataItem
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
Las acciones del controlador:
public ActionResult MyForm()
{
MyViewModel model = new MyViewModel();
model.Id = 1;
model.Data = new List<MyDataItem>()
{
new MyDataItem{ Id = 1, ParentId = 1, Name = "MyListItem1", Value = "SomeValue"}
};
return View(model);
}
[HttpPost]
public ActionResult MyForm(MyViewModel model)
{
//...
return View(model);
}
Aquí está la vista básica (sin el marcado de lista)
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>My View Model</legend>
@Html.HiddenFor(model => model.Id)
<div class="editor-label">
@Html.LabelFor(model => model.Property1)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Property1)
@Html.ValidationMessageFor(model => model.Property1)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Property2)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Property2)
@Html.ValidationMessageFor(model => model.Property2)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
Cuando se devuelve al controlador, obtengo los 2 valores de propiedad y un valor nulo para la propiedad ''Datos'' como se esperaba.
Si agrego el margen de la Lista de la siguiente manera (en base a la información en esta publicación de Scott Hanselman y la publicación de Phil Haack ):
<div class="editor-field">
@for (int i = 0; i < Model.Data.Count(); i++)
{
MyDataItem data = Model.Data[i];
@Html.Hidden("model.Data[" + i + "].Id", data.Id)
@Html.Hidden("model.Data[" + i + "].ParentId", data.ParentId)
@Html.Hidden("model.Data[" + i + "].Name", data.Name)
@Html.TextBox("model.Data[" + i + "].Value", data.Value)
}
</div>
La propiedad ''Datos'' del modelo se enlaza satisfactoriamente pero las otras propiedades son nulas.
Los valores de formulario publicados son los siguientes:
Id=1&Property1=test1&Property2=test2&model.Data%5B0%5D.Id=1&model.Data%5B0%5D.ParentId=1&model.Data%5B0%5D.Name=MyListItem1&model.Data%5B0%5D.Value=SomeValue
¿Hay alguna manera de poblar ambos conjuntos de propiedades o me falta algo obvio?
EDITAR:
Para aquellos de ustedes que son curiosos. Basado en la respuesta de MartinHN , el MartinHN original generado fue:
<div class="editor-field">
<input id="model_Data_0__Id" name="model.Data[0].Id" type="hidden" value="1" />
<input id="model_Data_0__ParentId" name="model.Data[0].ParentId" type="hidden" value="1" />
<input id="model_Data_0__Name" name="model.Data[0].Name" type="hidden" value="MyListItem1" />
<input id="model_Data_0__Value" name="model.Data[0].Value" type="text" value="SomeValue" />
</div>
El nuevo marcado generado es:
<div class="editor-field">
<input id="Data_0__Id" data-val="true" name="Data[0].Id" type="hidden" value="1" data-val-number="The field Id must be a number." data-val-required="The Id field is required." />
<input id="Data_0__ParentId" name="Data[0].ParentId" type="hidden" value="1" data-val="true" data-val-number="The field ParentId must be a number." data-val-required="The ParentId field is required." />
<input id="Data_0__Name" name="Data[0].Name" type="hidden" value="MyListItem1" />
<input id="Data_0__Value" name="Data[0].Value" type="text" value="SomeValue" />
</div>
Lo que resulta en los siguientes valores publicados:
Id=1&Property1=test1&Property2=test2&Data%5B0%5D.Id=1&Data%5B0%5D.ParentId=1&Data%5B0%5D.Name=MyListItem1&Data%5B0%5D.Value=SomeValue
Note que no hay ''modelo''. en el nombre y valores publicados ...
Alternativamente, podría haber creado un EditorTemplate
para su ViewModel anidado de la siguiente manera.
@model MyDataItem
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.ParentId)
@Html.HiddenFor(model => model.Name)
@Html.TextBoxFor(model => model.Value)
Cree una carpeta llamada ''EditorTemplates'' en su carpeta ''Shared'' y guarde lo anterior como ''MyDataItem.cshtml''.
Luego, en su Vista, solo llame al siguiente en lugar del bucle foreach
:
@Html.EditorFor(model => model.Data)
Se siente un poco menos hackier IMO :)
Intente cambiar el código de la recopilación de datos a esto y deje que MVC se encargue de la denominación:
<div class="editor-field">
@for (int i = 0; i < Model.Data.Count(); i++)
{
@Html.HiddenFor(m => m.Data[i].Id)
@Html.HiddenFor(m => m.Data[i].ParentId)
@Html.HiddenFor(m => m.Data[i].Name)
@Html.TextBoxFor(m => m.Data[i].Value)
}
</div>
Solo mis 2 centavos, pero algo que vale la pena notar con este problema: el miembro de datos en el Modelo de visualización debe definirse como una propiedad pública para que el enlace del modelo de devolución funcione. Tuve un problema muy similar al anterior pero utilicé un miembro de datos públicos en mi Modelo de Vista. El mismo HTML se genera como se muestra arriba y todo se ve bien, pero la carpeta del modelo arrojó una colección vacía. Vale la pena ver por ...