Передача массивов и сложных данных в контроллер

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 31.10.2015

Из предыдущих тем мы узнали, как передавать отдельные объекты из представления в методы действия контроллера в качестве параметров. Но в реальности может возникнуть ситуация, что потребуется передать в метод не один объект типа int или какой-нибудь модели, а сразу несколько объектов. Посмотрим на некоторые возможные случаи.

Передача коллекции

Определим следующую форму в представлении:

@using (Html.BeginForm())
{
    @Html.TextBox("names")
    @Html.TextBox("names")
    @Html.TextBox("names")
    @Html.TextBox("names")
    <input type="submit" />
}

Таким образом, у нас в html-разметке будет создано четыре элемента input

<form action="/Home/Array" method="post">
<input id="names" name="names" type="text" value="" />
<input id="names" name="names" type="text" value="" />
<input id="names" name="names" type="text" value="" />
<input id="names" name="names" type="text" value="" />
    <input type="submit" />
</form>

Поэтому при отправке формы будет формироваться коллекция из names, состоящая из четырех элементов. И в методе контроллера мы сможем получить все эти элементы:

[HttpPost]
public string Array(List<string> names)
{
    string fin="";
    for (int i = 0; i < names.Count; i++)
    {
        fin += names[i] + ";  ";
    }
    return fin;
}

Передача коллекции объектов модели

Мы можем передать в представление массив объектов некоторой модели, например, модели Book:

[HttpGet]
public ActionResult Add()
{
    return View(db.Books.ToList());
}

Чтобы вывести объекты для редактирования в представление мы можем использовать следующую конструкцию:

@model List<BookStore.Models.Book>
.......................................
@using (Html.BeginForm())
{
    for(int i=0; i<Model.Count; i++)
    {
        <h4>Книга № @(i+1)</h4>
        
        @: Name: @Html.EditorFor(m=>m[i].Name)
        @: Author: @Html.EditorFor(m => m[i].Author)
        @: Price: @Html.EditorFor(m => m[i].Price)
    }
    <input type="submit" />
}

Так мы сгенерируем для каждого объекта набор полей для редактирования его свойств. И после нажатия кнопки весь данный массив отправится на сервер, где его можно получить таким образом:

[HttpPost]
public string Add(List<Book> books)
{
	//........................
}

Передача разных объектов одной модели

В предыдущем случае мы передавали коллекцию объектов модели Book. Однако может возникнуть ситуация, когда мы должны разграничить как-то переданные объекты, а не рассматривать их как одну коллекцию. Например, метод контроллера может выглядеть так:

[HttpPost]
public string Add(Book book, Book myBook)
{
	//........................
}

Мы используем два отдельных объекта Book. Как мы можем передать их из представления в контроллер? Допустим, теперь, что один объект мы передаем в качестве модели представления, а другой создаем в том же представлении:

@using BookStore.Models
@model Book
@{
    ViewBag.Title = "Array";
}
@{
    Book myBook = new Book() { Name = "Мартин Иден", Author = "Джек Лондон", Price = 190 };
}
<h2>Книги</h2>

@using (Html.BeginForm())
{
    @Html.EditorFor(m=>myBook)
    @Html.EditorForModel()
    <input type="submit" />
}

Одну модель мы передаем из контроллера в представление:

[HttpGet]
public ActionResult Array()
{
    Book firstBook = db.Books.ToList<Book>().FirstOrDefault();
    return View(firstBook);
}

Вторую модель - myBook мы создаем уже в самом представлении. Все поля модели генерируются с помощью хелпера @Html.EditorFor(m=>myBook). Обратите внимание на имя модели - myBook. Так как мы ожидаем, что данный объект должен быть передан в метод в качестве параметра myBook, то он должен иметь точно такое же имя, а не произвольное.

Таким образом, мы можем передать на сервер два разных объекта одной модели.

Передача сложных объектов

Допустим, у нас есть следующая модель:

public class Book
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Book> Books { get; set; }
}

Модель автора содержит ссылку на коллекцию книг. В контроллере мы получаем эту модель:

[HttpPost]
public ActionResult GetAuthor(Author author)
{
    return View();
}

Тогда представление могло бы выглядеть так:

@model ArrayPostApp.Models.Author

<h2>Добавление книг</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    <div class="authorBlock">
        <label>Имя автора</label>
        <input type="text" name="name" />
    </div>
    <div id="booksBlock">
        <div class="bookItem">
            <h4>Книга № 1</h4>
            <div>
                <label>Название</label>
                <div>
                    <input type="text" name="Books[0].name" />
                </div>
            </div>
        </div>
        
    </div>
    <p><a class="addLink">Добавить новый элемент</a></p>
    <p><input type="submit" value="Добавить" /></p>
}

@section Scripts {
   <script>
       $(function () {
           var i = 0;
           $('.addLink').click(function()
           {
               i++;
               var html2Add= "<div class='bookItem'>"+
            "<h4>Книга № "+(i+1) + "</h4>"+
            "<div><label>Название</label><div>"+
                    "<input type='text' name='Books["+i+"].name' />"+
                "</div></div></div>";
               $('#booksBlock').append(html2Add);
           })
       })
    </script>
}

Так как модель Author содержит набор книг в свойстве Books, то атрибут name соответствующих текстовых элементов должно иметь следующую форму: name="Books[0].name". С помощью кода javascript мы можем динамически добавить новые элементы:

Отправка в контроллер MVC массивов
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850