Как я могу связать вложенные ViewModels из View в Controller в MVC3? - PullRequest
25 голосов
/ 18 апреля 2011

Я занимаюсь разработкой приложения ASP.NET MVC 3 на C # и использую Razor.Сейчас я имею дело с проблемой, связанной с привязкой объектов через ViewModels, передаваемые / получаемые в / из View контроллером.Давайте сделаем это ясно.У меня есть следующие ViewModels:

public class ContainerViewModel
{
   public int ContainerId {get; set;}
   public string ContainerName {get; set;}
   public List<ItemPostModel> ItemData {get; set;}
}

public class ItemPostModel
{ 
   public int ItemId {get; set;}
   public string ItemName {get; set;}
   public int ItemValue {get; set;}
}

ContainerViewModel используется для передачи данных в представление.Его свойства ContainerId и ContainerName используются только для отображения.Свойство List<ItemPostModel> должно быть заполнено с использованием формы .Вид выглядит примерно так (это упрощенная версия):

<strong>@Model.ContainerName</strong>


@using (Html.BeginForm()) 
{
    <fieldset>
    @foreach(var item in Model.ItemData)
    {
       @Html.TextBox(item.ItemId);
       @Html.TextBox(item.ItemName);
       @Html.TextBox(item.ItemValue);

       <p>
           <input type="submit" value="Save" />
       </p>
    }
    </fieldset>
}

Контроллер соответствующие методы действия следующие:

public ActionResult UpdateItems()
{
   //fill in the ContainerViewModel lcontainer

   return View("UpdateItems", lcontainer);
}

[HttpPost]
public ActionResult UpdateItems(int containerId, ItemPostModel itemData)
{
   //store itemData into repository
}

Проблема в том, что с этим кодом ItemPostModel itemData , передаваемое в Post ActionMethod UpdateItems , всегда пусто. containerId правильно передан.Тот же результат, если я использую следующий код в контроллере (очевидно, не DRY):

[HttpPost]
public ActionResult UpdateItems(ContainerViewModel container)
{
   //extract itemData from ContainerViewModel container
   //store itemData into repository
}

Как я могу "обучить" приложению, которому я хочу, чтобы элементы формы сохранялись в List<ItemPostModel>?Должен ли я изменить ModelBinder или есть более простой способ выполнить эту задачу?Спасибо всем за ваши ответы.

1 Ответ

26 голосов
/ 18 апреля 2011

Не пишите циклы в представлении.Используйте шаблоны редактора:

<strong>@Model.ContainerName</strong>
@using (Html.BeginForm()) 
{
    <fieldset>
        @Html.EditorFor(x => x.ItemData)
        <input type="submit" value="Save" />
    </fieldset>
}

и внутри соответствующего шаблона редактора (~/Views/Shared/EditorTemplates/ItemPostModel.cshtml):

@model ItemPostModel
@Html.TextBox(x => x.ItemId)
@Html.TextBox(x => x.ItemName)
@Html.TextBox(x => x.ItemValue)

И в действии контроллера вам может потребоваться указать префикс:

[HttpPost]
public ActionResult UpdateItems(
    int containerId, 
    [Bind(Prefix = "ItemData")]ItemPostModel itemData
)
{
   //store itemData into repository
}

и это должно быть почти все.Шаблон редактора позаботится о создании правильных имен полей ввода для привязки к работе.

...