ASP.NET MVC 3 сбор / передача данных из представлений с вложенными коллекциями - данные теряются в процессе - PullRequest
0 голосов
/ 04 ноября 2011

Моя модель представляет собой простое представление родитель / потомок, похожее на это

public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Child> Children { get; set; } 
}

public class Child
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Теперь я хочу создать страницу, которая позволит мне редактировать / создавать детей - по одному ребенку за раз просто отлично. Я хочу передать родителя в представление, создать текстовое поле для Child.Name, собрать все, что пользователь вводит, а затем сохранить его в базе данных.

Итак, в первом действии CreateParent в моем контроллере я создаю Parent (с передачей Id, так как мне нужно отслеживать этот Id [после всего, что мне нужно знать, для какого ParentId мне нужно добавить дочерний элемент]) выглядит это:

[HttpGet]
public ActionResult CreateChild(int id)
{
    var newParent = new Parent { 
        Id = id, Children = new List<Child> { new Child { Name = "ChildName" } } };
    return View("~/Views/Home/CreateParent.cshtml", newParent);
}

Страница загружена, пользователь заполняет данные и нажимает «ОК». Затем выполняется это действие:

[HttpPost]
public ActionResult CreateChild(Parent parent)
{
      return View("~/Views/Home/ViewChildren.cshtml", AddChild(parent));
}

AddChild (parent) - это закрытая функция, которая имеет дело с сохраняющимися дочерними элементами для данного родителя и возвращает родительскую модель с обновленными дочерними элементами.

Вот моя проблема / вопрос: данные теряются между вызовами. Когда я создаю родительский элемент в [HttpGet], все в порядке, я вижу, что значения правильно установлены в отладчике, но когда я заполняю дочерние данные и нажимаю «OK» в [HttpPost], родительский объект приходит со всеми значениями, включая мой недавно заполненный Child as null (на самом деле только Id является полем, кажется, переносится, что я тоже не понимаю). Почему?

Я могу добавить, что если я делаю это с видом, который напечатан для Child, то это работает. Я не могу просто передать ребенка, потому что мне также нужно отслеживать / переносить идентификатор родителя. Я тоже этого не понимаю.

Вот представления (во-первых, чтобы просмотреть детей под родителем), и это работает нормально:

@model Parent

@{
    ViewBag.Title = "AddChild";
}
<h2>Children for parent @Model.Name </h2>
<p>
    @Html.ActionLink("Create New", "CreateChild", new {id = @Model.Id})
</p>

<table>
    <tr>
        <th>
            Name
        </th>
    <tr>
@foreach (var child in @Model.Children) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => child.Name)
        </td>
        <td>
            @Html.ActionLink("Delete", "Delete", new { id=child.Id })
        </td>
    </tr>
}
</table>

Вот представление для создания дочернего элемента под родителем:

@model Parent
@{
    ViewBag.Title = "CreateChild";
}

<h2>Create new child for @Model.Name</h2>

@using (Html.BeginForm())
{ 
    <table>
    <tr>
        <td>
            Name:
        </td>
    </tr>

@foreach (var child in @Model.Children)
{
    <tr>
        <td>
            @Html.EditorFor(modelItem => child.Name)
        </td>
    </tr>
}
</table>
<input id="submit" name="submit" type="submit" value="Save" />
}

Поэтому, когда я нажимаю «Сохранить», родитель приходит только с идентификатором, установленным на значение, которое было передано. Все остальное устанавливается на ноль. Включая имя родителя и детей.

Вот метод AddChild:

private Parent AddChild(Parent parent)
{
   var updatedParent = GetParent(int parent.Id);
   updatedParent.Children.Add(parent.Children[0]); // this obviously fails as Children is NULL
   return updatedParent;
}

1 Ответ

1 голос
/ 05 ноября 2011

Parent.Name НЕДЕЙСТВИТЕЛЕН, потому что вы НЕ РАЗМЕЩАЕТЕ это.Вам необходимо добавить @Html.TextBoxFor() или @Html.HiddenFor().Но вам это не нужно, потому что вы загружаете сохраненного родителя.

Для детей вместо этого попробуйте цикл for.

@for (var n = 0; n < Model.Children.Count; n++)
{
    <tr>
        <td>
            @Html.EditorFor(modelItem => Model.Children[n].Name)
        </td>
    </tr>
}

Это связано с тем, какModelBinder работает.Знай это хорошо, ModelBinder твой друг;).

Редактировать: прежде чем я получу все милое в конце, я хотел упомянуть - обратите внимание на то, как помощник отображает входные данныеАтрибут name с циклом for (в отличие от цикла foreach), чтобы понять, что ищет ModelBinder.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...