#c# #asp.net-mvc-3
#c# #asp.net-mvc-3
Вопрос:
Моя модель представляет собой простое родительское / дочернее представление, выглядящее следующим образом
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; }
}
Теперь я хочу создать страницу, которая позволит мне редактировать / создавать дочерние элементы — по одному дочернему элементу за раз просто отлично. Я хочу передать родительский элемент в представление, создать текстовое поле для дочернего элемента.Назовите, соберите все, что вводят пользователи, а затем сохраните это в базе данных.
Итак, в первом действии CreateParent в моем контроллере я создаю родительский элемент (с переданным идентификатором, поскольку мне нужно отслеживать этот идентификатор [в конце концов, мне нужно знать, для какого родительского элемента мне нужно добавить дочерний элемент]) выглядит так:
[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], родительский элемент получает все значения, включая мой недавно заполненный дочерний элемент как null (на самом деле переносится только поле Id is, которое я также не понимаю). Почему?
Я могу добавить, что если я сделаю это с представлением, которое введено для дочернего элемента, тогда это сработает. На самом деле я не могу просто передать дочерний элемент, потому что мне также нужно отслеживать идентификатор родителя / переноса. Я тоже этого не понимаю.
Вот представления (первое — для просмотра дочерних элементов под родительским), и это работает нормально:
@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" />
}
Поэтому, когда я нажимаю «Сохранить», родитель приходит только с идентификатором, установленным на значение, которое было передано. Все остальное имеет значение null. Включая имя родительского элемента, а также дочерних элементов.
Вот метод 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. Не могли бы вы опубликовать свой код представления и
AddChild
пожалуйста?
Ответ №1:
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
атрибут inputs с помощью for
цикла (в отличие от foreach
цикла), чтобы понять, что ModelBinder
ищет.