Я пытаюсь настроить представление, в котором пользователь может добавлять и удалять из списка людей. Когда я отлаживаю, после удаления элемента с помощью RemoveAt(i)
список обновляется правильно, и когда я проверяю модель во время создания представления, удаленного элемента там нет. Однако после того, как я вызываю EditorFor(x => name)
в цикле for
, который отображает каждый элемент в списке, отображается правильное количество элементов, но значения не совпадают с тем, что содержится в модели.
Я использую методы из этого ответа для отображения каждого элемента.
Соответствующий код:
Контроллер:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Persons(IList<Person> persons, string command)
{
if (!ModelState.IsValid && !command.StartsWith("Delete"))
return View(persons);
if (command == "AddNew")
{
List<Person> newPersons = persons?.ToList() ?? new List<Person>();
newPersons.Add(new Person());
return View(newPersons);
}
if (command.StartsWith("Delete"))
{
if (int.TryParse(command.Substring(6), out int i))
persons.RemoveAt(i);
else
ModelState.AddModelError("", "There was an error deleting the person.");
return View(persons);
}
return RedirectToAction(command == "Back" ? "Index" : "Summary");
}
Person.cs (модель)
private string firstName;
private string middleName;
private string lastName;
[Required(AllowEmptyStrings = false)]
[Display(Name = "First Name")]
public string FirstName
{
get => firstName;
set => firstName = value?.Trim();
}
[Display(Name = "Middle Name")]
public string MiddleName
{
get => middleName;
set => middleName = value?.Trim();
}
[Required(AllowEmptyStrings = false)]
[Display(Name = "Last Name")]
public string LastName
{
get => lastName;
set => lastName = value?.Trim();
}
Лица.cshtml:
@model IEnumerable<Person>
<div class="text-center">
<button type="submit" name="command" value="AddNew" class="btn btn-primary btn-lg">
Add another person
</button>
</div>
{
int i = 0;
foreach (Person person in Model)
{
@Html.EditorFor(x => person, "PersonTemplate", $"Persons[{i++}]")
}
}
<script type="text/javascript>
$(document).on("click", "button[value='Delete']", function() {
const r = $(this).parent().prev().find("select").attr("name");
const s = r.substring(8, r.indexOf("]"));
$(this).val(`Delete${s}`);
})
</script>
PersonTemplate.cshtml:
<div class="row px-3 pb-3">
<div class="col-lg-3 col-md-6">
@Html.LabelFor(x => x.FirstName, new { @class = "required" })
@Html.EditorFor(x => x.FirstName, new { htmlattributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(x => x.FirstName)
</div>
<div class="col-lg-3 col-md-6">
@Html.LabelFor(x => x.MiddleName)
@Html.EditorFor(x => x.MiddleName, new { htmlattributes = new { @class = "form-control" } })
</div>
<div class="col-lg-4 col-md-7">
@Html.LabelFor(x => x.LastName, new { @class = "required" })
@Html.EditorFor(x => x.LastName, new { htmlattributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(x => x.LastName)
</div>
</div>
<button type="submit" name="command" value="Delete" class="btn btn-outline-danger">
Delete
</button>
Добавление нового пустого элемента в список работает нормально. Удаление элемента работает, вплоть до команды EditorFor. Вот пример сценария, через который я прохожу:
- на экране 3 имени: Боб Смит, Ларри Джонс, Энн Уокер.
- Я нажимаю кнопку «Удалить» рядом с Ларри Джонсом.
- По мере того, как я выполняю действие контроллера,
command
= «Удалить1», поэтому я знаю, что javascript, который определяет, какой из них нужно удалить, работает. int.TryParse()
возвращаетi = 1
, поэтому я знаю, что эта часть тоже работает.- Когда я просматриваю объект
persons
после строкиRemoveAt(i)
, в списке есть два объекта Person: Bob Smith и Anne Walker. - Когда я вхожу в представление и проверяю объект модели, есть два объекта
Person
: Боб Смит и Энн Уокер. - В цикле
for
при вызовеEditorFor()
первым объектомPerson
, который отправляется в шаблон, является Боб Смит. Второй объектPerson
— Энн Уокер. - Вот ключевой момент, который я не понимаю: в PersonTemplate.cshtml
this.Model
имеетFirstName = "Anne"
иLastName = "Walker"
, но MvcHtmlString, сгенерированный@Html.EditorFor(x => x.FirstName)
, возвращает следующее:
<input class="text-box single-line" id="Persons_1__FirstName" name="Persons[1].FirstName" type="text" value="Larry" />
@Html.EditorFor(x => x.LastName)
возвращает:
<input class="text-box single-line" id="Persons_1__LastName" name="Persons[1].LastName" type="text" value="Jones" />
Что случилось с Энн Уокер? В PersonTemplate this.Model
по-прежнему показывает FirstName = "Anne"
и LastName = "Walker"
, но вместо них во входных значениях используется Ларри Джонс.
Это происходит независимо от того, какой из них я удаляю в списке. Если у меня есть 5 человек в списке, и я удаляю человека № 1, то в представлении отображаются лица 1, 2, 3 и 4. Если я удаляю человека 4, он по-прежнему отображает людей 1, 2, 3 и 4. Если Я удаляю человека 5, он отображает людей 1, 2, 3 и 4. Почему он не отображает правильное значение из модели?