Подтвердить что ты не робот

Привязка модели к списку MVC 4

Есть ли шаблон для привязки IList элементов к представлению. Кажется, у меня проблемы с HttpPost. Я знаю, что Фил Хаак написал хорошую статью, но она устарела, и он сказал, что у них может быть проблема с MVC 4.

4b9b3361

Ответ 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.