Есть ли шаблон для привязки IList элементов к представлению. Кажется, у меня проблемы с HttpPost. Я знаю, что Фил Хаак написал хорошую статью, но она устарела, и он сказал, что у них может быть проблема с MVC 4.
Привязка модели к списку MVC 4
Ответ 1
Вот как я это делаю, если мне нужна форма, отображаемая для каждого элемента, и входы для различных свойств. Действительно зависит от того, что я пытаюсь сделать, хотя.
ViewModel выглядит так:
public class MyViewModel
{
public List<Person> Persons{get;set;}
}
Просмотр (с BeginForm, конечно):
@model MyViewModel
@for( int i = 0; i < Model.Persons.Count(); ++i)
{
@Html.HiddenFor(m => m.Persons[i].PersonId)
@Html.EditorFor(m => m.Persons[i].FirstName)
@Html.EditorFor(m => m.Persons[i].LastName)
}
Действие:
[HttpPost]public ViewResult(MyViewModel vm)
{
...
Обратите внимание, что при отправке только те свойства, у которых есть доступные входы, будут иметь значения. Если у человека было свойство .SSN, оно не было бы доступно в post-действии, потому что оно не было полем в форме.
Обратите внимание, что способ привязки модели MVC работает, он будет искать только последовательные идентификаторы. Таким образом, делать что-то вроде этого, когда вы условно скрываете элемент, не приведет к тому, что он не привяжет какие-либо данные после 5-го элемента, потому что, как только он встретит пробел в идентификаторах, он перестанет привязываться. Даже если бы было 10 человек, вы получили бы первые 4 на обратной передаче:
@for( int i = 0; i < Model.Persons.Count(); ++i)
{
if(i != 4)//conditionally hide 5th item,
{ //but BUG occurs on postback, all items after 5th will not be bound to the the list
@Html.HiddenFor(m => m.Persons[i].PersonId)
@Html.EditorFor(m => m.Persons[i].FirstName)
@Html.EditorFor(m => m.Persons[i].LastName)
}
}
Ответ 2
Чистым решением может быть создание универсального класса для обработки списка, поэтому вам не нужно создавать разные классы каждый раз, когда вам это нужно.
public class ListModel<T>
{
public List<T> Items { get; set; }
public ListModel(List<T> list) {
Items = list;
}
}
и когда вы вернете View, вам просто нужно сделать следующее:
List<customClass> ListOfCustomClass = new List<customClass>();
//Do as needed...
return View(new ListModel<customClass>(ListOfCustomClass));
затем определите список в модели:
@model ListModel<customClass>
и готов к работе:
@foreach(var element in Model.Items) {
//do as needed...
}
Ответ 3
~ контроллер
namespace ListBindingTest.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
List<String> tmp = new List<String>();
tmp.Add("one");
tmp.Add("two");
tmp.Add("Three");
return View(tmp);
}
[HttpPost]
public ActionResult Send(IList<String> input)
{
return View(input);
}
}
}
~ Сильно типизированный индексный указатель
@model IList<String>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
@using(Html.BeginForm("Send", "Home", "POST"))
{
@Html.EditorFor(x => x)
<br />
<input type="submit" value="Send" />
}
</div>
</body>
</html>
~ Сильно напечатано Отправить
@model IList<String>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Send</title>
</head>
<body>
<div>
@foreach(var element in @Model)
{
@element
<br />
}
</div>
</body>
</html>
Это все, что вам нужно было сделать человеку, изменить его модель MyViewModel на IList.