#c# #asp.net #asp.net-mvc
#c# #asp.net #asp.net-mvc
Вопрос:
Я хочу сделать что-то похожее на то, что объясняется в этом вопросе: я хочу отредактировать список данных.
Разница в том, что база не является списком.
(Я использую VS 2013, так что это не старый материал.)
Моя модель представления:
public class SampleViewModel
{
// ... other properties for editing ...
// The list property
public List<SampleListItemViewModel> ItemList { get; set; }
}
public class SampleListItemViewModel
{
// For display only. It has an ID field to identify the row.
public MyEntity Item { get; set; }
// I want to modify this!
public bool IsChecked { get; set; }
}
Моя попытка просмотра:
@model My.Namespace.SampleViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<!-- ... normal editing, MVC generated ... -->
<!-- BEGIN LIST EDIT -->
<table>
<tr>
<th>
Is Applicable
</th>
<!-- ... -->
</tr>
@foreach (var doc in Model.ItemList)
{
@Html.HiddenFor(modelItem => doc.Document.CRMDocumentId)
<tr>
<td>
@Html.EditorFor(modelItem => doc.IsChecked)
<!-- @Html.ValidationMessageFor(modelItem => doc.IsChecked) -->
</td>
<!-- ... other non-editable display fields, e.g. name ... -->
</tr>
}
<!-- END LIST EDIT -->
<!-- ... -->
}
Когда я создаю представление, оно показывает все так, как я хочу, но когда я нажимаю «Создать», список элементов равен нулю.
РЕДАКТИРОВАТЬ — Дополнительная информация
Контроллер:
public ActionResult Create(int? id)
{
var item = // ...populate...
// I confirmed that ItemList has values.
return View(item);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(SampleViewModel item)
{
// This is null
var list = item.ItemList;
// ignoring all else for now
return View(item);
}
Комментарии:
1. Что вы делаете, когда нажимаете на ссылку «Создать»?? Не могли бы вы показать нам код??
2. Хорошо, можешь попробовать это — создай конструктор SampleViewModel и инициализируй свойство ItemList следующим образом — ItemList = new List<SampleListItemViewModel>() в конструкторе, а затем проверь…
3. Я пока мало что делаю в контроллере, но я обновил свой вопрос. Я подтвердил, что список элементов имеет значения.
Ответ №1:
Чтобы связать сложные объекты, нам нужно предоставить индекс для каждого элемента, а не полагаться на порядок элементов. Это гарантирует, что мы сможем однозначно сопоставить представленные свойства с правильным объектом.
Замените foreach
цикл на for
loop:
@for (int i=0; i<Model.ItemList.Count; i )
{
@Html.HiddenFor(modelItem => modelItem.ItemList[i].Document.CRMDocumentId)
<tr>
<td>
@Html.EditorFor(modelItem => modelItem.ItemList[i].IsChecked)
@Html.ValidationMessageFor(modelItem => modelItem.ItemList[i].IsChecked)
</td>
</tr>
}
ПРИМЕЧАНИЕ:
Обратите внимание, что индекс должен представлять собой непрерывную последовательность целых чисел, начинающихся с 0 и увеличивающихся на 1 для каждого элемента
Также для каждого свойства в списке, которое вы не хотите, чтобы пользователь редактировал, например, идентификатор пользователя и т.д., Добавьте @Html.HiddenFor(..)
для этого свойства, иначе оно будет отправлено null
на сервер, и если для них создано скрытое поле, их не будет NULL
.
Более подробную информацию вы можете увидеть ЗДЕСЬ
Также см. Привязку модели к списку
Комментарии:
1. Спасибо! Кроме того, для каждого
@Html.DisplayFor(..)
в списке также добавьте@Html.HiddenFor(..)
, потому что тогда ASP отправит данные только для просмотра обратно на сервер, и они не будут равны нулю, если страница перезагрузится с ошибками проверки.2. @PeetBrits да, если вы не создадите скрытое поле для объекта модели, который вы не показываете в представлении, оно будет опубликовано с нулевым значением