2015-05-31 5 views
5

в моем представлении создать Я хочу дать пользователю возможность создать список объектов (одного типа). Поэтому я создал таблицу в представлении, включающую каждое поле ввода в каждой строке. Количество строк, соответствующих «создаваемым» объектам, является фиксированным числом.Создайте несколько объектов одного и того же типа в одном и том же виде

Допустим, есть классная книга, включающая в себя два титула собственности и автора, и пользователь должен иметь возможность создавать 10 или менее книг.

Как я могу это сделать?

Я не знаю, как передать список объектов (которые привязаны) к контроллеру. Я пробовал:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create(ICollection<Book> bookList) 
    { 
     if (ModelState.IsValid) 
     { 
      foreach(var item in bookList) 
       db.Books.Add(item); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(articlediscounts); 
    } 

И по мнению это:

<fieldset> 
    <legend>Book</legend> 

    <table id="tableBooks" class="display" cellspacing="0" width="100%"> 
      <thead> 
       <tr> 
        <th>Title</th> 
        <th>Author</th> 
       </tr> 
      </thead> 
      <tbody> 
       @for (int i = 0; i < 10 ;i++) 
       { 
        <tr> 
         <td> 
          <div class="editor-field"> 
           @Html.EditorFor(model => model.Title) 
           @Html.ValidationMessageFor(model => model.Title) 
          </div> 
         </td> 
         <td> 
          <div class="editor-field"> 
           @Html.EditorFor(model => model.Author) 
           @Html.ValidationMessageFor(model => model.Author) 
          </div> 
         </td> 
        </tr> 
       } 
      </tbody> 
     </table> 

    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 

Как Booklist имеет нулевое значение, он не работает, и я не знаю, как поставить все созданные объекты в этом списке.

Если у вас есть предложения, я был бы очень благодарен.

ответ

0

Тот факт, вы используете @Html.EditorFor(model => model.Title) предполагает, что вы объявили модель в представлении как

@model yourAssembly.Book 

, который позволяет размещать обратно только один Book поэтому метод POST должны быть

public ActionResult Create(Book model) 

Обратите внимание, что текущая реализация создает входы, которые выглядят как

<input id="Title" name="Title" ... /> 

В name атрибуты не имеют шагового (они должны были бы быть name="[0].Title", name="[1].Title" и т.д.), так что не может связываться с коллекцией, и ее также недействителен HTML из-за повторяющихся id атрибутов.

Если вы хотите создать ровно 10 книг, то вам необходимо инициализировать коллекцию в методе GET и передать коллекцию в целях

public ActionResult Create() 
{ 
    List<Book> model = new List<Book>(); 
    for(int i = 0; i < 10;i++) 
    { 
    model.Add(new Book()); 
    } 
    return View(model); 
} 

и в представлении

@model yourAssembly.Book 
@using (Html.BeginForm()) 
{ 
    for(int i = 0; i < Model.Count; i++) 
    { 
    @Html.TextBoxFor(m => m[i].Title) 
    @Html.ValidationMessageFor(m => m[i].Title) 
    .... // ditto for other properties of Book 
    } 
    <input type="submit" .. /> 
} 

, который будет теперь привязывайте к своей коллекции, когда вы отправляете сообщение от

public ActionResult Create(List<Book> bookList) 

Примечание: коллекция должна быть List<Book> в случае, если вам нужно вернуть представление.

Однако это может заставить пользователя создать все 10 книг, в противном случае проверка может завершиться неудачно (как предложено вашим использованием @Html.ValidationMessageFor()). Лучшим подходом является динамическое добавление новых элементов Book в представление с использованием вспомогательного метода BeginCollectionItem (refer example) или шаблона клиента согласно this answer.

+0

«Что позволяет отправлять только одну книгу» не является правильным. Модель просмотра GET не должна соответствовать модели POST. Параметры post action привязаны на основе полей в форме, а не '@ model 'представления. –

+0

@ freedomn-m, Посмотрите на код в представлении OP - они создают ввод с именем 'name =" title "и одним вводом с именем' name = "Author", который будет возвращаться к одному объекту 'Book'! –

+0

«@model yourAssembly.Book .., который позволяет отправлять только одну книгу» - ваше заявление только о публикации одной книги относится к '@ model', а не к именам ввода. Остальная часть сообщения с 'm [i] .Title' и т. Д. Хороша, просто эта часть. –

0

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

public class SavedBooks{ 
    public List<Book> Books { get; set; } 
} 

Тогда Book класс должен был бы иметь эти 2 реквизита:

public class Book { 
    public string Title { get; set; } 
    public string Author { get; set; } 
} 

Затем измените ваш контроллер использовать эту модель:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create(SavedBooks model) 

Затем создайте яваскрипт метод (с помощью JQuery), чтобы создать объект JSON, который соответствует структуре контроллеров SavedBooks класса:

var json = { Books: [ { Title: $('#title_1').val(), Author: $('#Author_1').val() } , 
         { as many items as you want } 
        ] 
      }; 
$.ajax(
{ 
    url: "/Controller/Create", 
    type: "POST", 
    dataType: "json", 
    data: json 
}); 
2

Скотт Hanselman имеет некоторые подробности о передаче массивов для управления MVC связывания: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

Что существенно: убедитесь, что ваши элементы управления имеют правильные названия: с помощью индекса для списков

Измените свой цикл, чтобы что-то вроде :

@for (int i = 0; i < 10 ; i++) 
{ 
    <tr> 
     <td> 
      <div class="editor-field"> 
       <input type="text" name="book[" + i + "].Title" /> 
      </div> 
     </td> 
     <td> 
      <div class="editor-field"> 
       <input type="text" name="book[" + i + "].Author" /> 
      </div> 
     </td> 
    </tr> 
} 

это будет автоматически связываться с вашим действием по почте.

[HttpPost] 
public ActionResult Create(IList<Book> bookList) 

Вы можете показать/скрыть их по мере необходимости или использовать JS/JQuery, чтобы добавить их динамически

Edit: Как правильно наблюдали Стивен Муеке, выше ответ только касается связывания из формы + к HttpPost, который, как представляется, является акцентом на вопрос.

Почтовое действие в исходном сообщении несовместимо с представлением. В OP довольно много недостающего кода, который может быть или не быть релевантным, но стоит заметить, что если ваше представление относится к одной модели, то ваш код отказа на ModelState.IsValid должен вернуть одну модель или ваше представление должно быть для IList (или аналогичный), в противном случае вы не получите проверку на стороне сервера (но вы все равно можете получить подтверждение на стороне клиента, если вручную добавить его в <input>s)

Смежные вопросы