2015-05-31 19 views
5

trong chế độ xem tạo của tôi Tôi muốn cung cấp cho người dùng khả năng tạo danh sách các đối tượng (cùng loại). Do đó, tôi đã tạo một bảng trong chế độ xem bao gồm cả mỗi trường nhập trong mỗi hàng. Số hàng tương ứng với các đối tượng "có thể tạo" tương ứng là một số cố định.Tạo nhiều hơn một đối tượng cùng loại trong cùng một chế độ xem

Cho phép nói rằng có một cuốn sách lớp bao gồm hai thuộc tính tiêu đề và tác giả và người dùng sẽ có thể tạo hai hoặc ít sách hơn.

Tôi có thể làm như thế nào?

Tôi không biết cách chuyển danh sách các đối tượng (được gắn kết) vào bộ điều khiển. Tôi cố gắng:

[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); 
    } 

Và trong giao diện đó là:

<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> 

Như Booklist là null, nó không hoạt động và tôi không biết làm thế nào để đặt tất cả các đối tượng được tạo trong danh sách này.

Nếu bạn có bất kỳ đề xuất nào tôi sẽ rất biết ơn.

Trả lời

0

Việc bạn sử dụng @Html.EditorFor(model => model.Title) gợi ý rằng bạn đã tuyên bố mô hình trong giao diện như

@model yourAssembly.Book 

nào cho phép để viết lại chỉ một Book nên phương thức POST sẽ cần phải được

public ActionResult Create(Book model) 

Lưu ý rằng bạn triển khai hiện tại tạo các yếu tố đầu vào giống như

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

Thuộc tính name không có chỉ mục (chúng cần phải là name="[0].Title", name="[1].Title" v.v.) để không thể liên kết với bộ sưu tập và html cũng không hợp lệ do thuộc tính trùng lặp id.

Nếu bạn muốn tạo một cách chính xác 10 cuốn sách, sau đó bạn cần khởi tạo một bộ sưu tập trong phương thức GET và vượt qua các bộ sưu tập để xem

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

và trong giao diện

@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" .. /> 
} 

mà sẽ bây giờ liên kết với bộ sưu tập của bạn khi bạn POST tới

public ActionResult Create(List<Book> bookList) 

Lưu ý rằng bộ sưu tập phải là List<Book> trong trường hợp bạn cần trả lại chế độ xem.

Tuy nhiên điều này có thể buộc người dùng tạo tất cả 10 cuốn sách, nếu không xác thực có thể không thành công (như được đề xuất bởi việc bạn sử dụng @Html.ValidationMessageFor()). Cách tiếp cận tốt hơn là tự động thêm các mục Book mới trong chế độ xem bằng cách sử dụng phương thức trợ giúp BeginCollectionItem (refer example) hoặc mẫu ứng dụng khách theo this answer.

+0

"Chỉ cho phép đăng lại một cuốn sách" không đúng. Chế độ xem của GET không cần phải khớp với mô hình của POST. Các tham số hành động bài được ràng buộc dựa trên các trường trong biểu mẫu, không phải là '@ model' của khung nhìn. –

+0

@ freedomn-m, Nhìn vào mã trong giao diện của OP - chúng đang tạo đầu vào với 'name =" title "' và một đầu vào với 'name =" Author "' sẽ đăng lại đối tượng 'Book'! –

+0

"@model yourAssembly.Book .. cho phép bạn chỉ đăng lại một cuốn sách" - tuyên bố của bạn về việc chỉ đăng một cuốn sách đề cập đến '@ model' - không phải là tên đầu vào. Phần còn lại của bài viết với 'm [i] .Title' vv là tốt, chỉ là một phần. –

0

Bạn cần gửi đối tượng JSON có danh sách sách trong đó. Vì vậy, điều đầu tiên là tạo một lớp mẫu như thế này:

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

Sau đó, lớp Book sẽ phải có những 2 đạo cụ:

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

Tiếp theo, thay đổi điều khiển của bạn để sử dụng mô hình này:

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

Sau đó, tạo phương thức javascript (sử dụng jQuery) để tạo đối tượng JSON khớp với cấu trúc của bộ điều khiển SavedBooks lớp:

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

Scott Hanselman có một số chi tiết về đi qua mảng để kiểm soát MVC ràng buộc: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

Mà về cơ bản là: đảm bảo các điều khiển của bạn có tên chính xác: sử dụng một chỉ số cho các danh sách

Thay đổi của bạn cho vòng lặp để cái gì đó như :

@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> 
} 

sau đó sẽ tự động liên kết với hành động bài đăng của bạn.

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

Sau đó bạn có thể hiển thị/ẩn các theo yêu cầu hoặc sử dụng js/jquery để thêm chúng động

Sửa: Theo quan sát một cách chính xác bởi Stephen Muecke, câu trả lời ở trên chỉ liên quan đến việc ràng buộc từ mẫu + các trường vào HttpPost, mà dường như là trọng tâm của câu hỏi.

Tác vụ đăng trong bài đăng gốc không tương thích với chế độ xem. Có khá nhiều mã thiếu trong OP có thể có hoặc không có liên quan, nhưng đáng quan sát rằng nếu chế độ xem của bạn là cho một mô hình, thì mã lỗi của bạn trên ModelState.IsValid cần trả lại một mô hình hoặc chế độ xem của bạn IList (hoặc tương tự), nếu không bạn sẽ không nhận được xác thực phía máy chủ (nhưng bạn vẫn có thể nhận được xác thực phía máy khách nếu bạn thêm thủ công vào <input>s)

Các vấn đề liên quan