2011-12-20 29 views
10

TL; DR: Trong ứng dụng ASP.NET MVC3, tôi nên triển khai Chế độ xem cho phép tôi chỉnh sửa chi tiết của thực thể 'cha mẹ' cùng một lúc như chi tiết của danh sách các thực thể 'trẻ em'?Ràng buộc danh sách có thể chỉnh sửa của trẻ em

Cập nhật: Tôi chấp nhận @torm's answer vì ông cung cấp a link cung cấp cho một số lời giải thích là tại sao giải pháp hiện tại của tôi có thể tốt như nó được. Tuy nhiên, chúng tôi rất muốn nghe nếu có ai khác thay thế!

Tôi đã tìm kiếm và đọc (xem phần 'Tham khảo' ở cuối cho một số phát hiện cho đến nay). Tuy nhiên, tôi vẫn cảm thấy giống như có một cái gì đó 'mùi' với các giải pháp tôi tìm thấy cho đến nay. Tôi tự hỏi liệu có ai trong số các bạn có một câu trả lời hay gợi ý thanh lịch hơn (hoặc có thể giải thích tại sao điều này có thể là 'tốt như nó'). Cảm ơn bạn trước!

Vì vậy, đây là thiết lập:

Các Models:

public class Wishlist 
{ 
    public Wishlist() { Wishitems = new List<Wishitem>(); } 

    public long WishListId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 

    public virtual ICollection<Wishitem> Wishitems { get; set; } 
} 
public class Wishitem 
{ 
    public long WishitemId { get; set; } 
    public string Name { get; set; } 
    public int Quantity { get; set; } 
} 

Controller:

public class WishlistsController : Controller 
{ 
    private SandboxDbContext db = new SandboxDbContext(); 
    /* ... */ 
    public ActionResult Edit(long id) 
    { 
     Wishlist wishlist = db.Wishlists.Find(id); 
     return View(wishlist); 
    } 

    [HttpPost] 
    public ActionResult Edit(Wishlist wishlist) 
    //OR (see below): Edit(Wishlist wishlist, ICollection<Wishitem> wishitems) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Entry(wishlist).State = EntityState.Modified; 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(wishlist); 
    } 
    /* ... */ 
} 

The View: Views \ Danh sách mong ước \ Edit.cshtml

@model Sandbox.Models.Wishlist 
<h2>Edit</h2> 
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 
@using (Html.BeginForm()) 
{ 
    @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>Wishlist</legend> 
     @Html.HiddenFor(model => model.WishListId) 
     <div class="editor-label">@Html.LabelFor(model => model.Name)</div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Name) 
      @Html.ValidationMessageFor(model => model.Name) 
     </div> 
    </fieldset> 
    <table> 
     <tr> 
      <th> 
       Quantity 
      </th> 
      <th> 
       Name 
      </th> 
     </tr> 
     @for (var itemIndex = 0; itemIndex < Model.Wishitems.Count; itemIndex++) 
    { 
      @Html.EditorFor(item => Model.Wishitems.ToList()[itemIndex]) 
    } 
    </table> 
    <p> 
     <input type="submit" value="Save" /> 
    </p> 
} 

Mẫu Trình chỉnh sửa: Số lượt xem \ Shared \ EditorTemplates \ Wishitem.cshtml

@model Sandbox.Models.Wishitem 
<tr> 
    <td> 
     @Html.HiddenFor(item=>item.WishitemId) 
     @Html.TextBoxFor(item => item.Quantity) 
     @Html.ValidationMessageFor(item => item.Quantity) 
    </td> 
    <td> 
     @Html.TextBoxFor(item => item.Name) 
     @Html.ValidationMessageFor(item => item.Name) 
    </td> 
</tr> 

Điều gì đang diễn ra?

Quá trình cài đặt trên tạo ra một trang với các yếu tố đầu vào tiêu chuẩn cho 'mẹ' mô hình thích:

<input class="text-box single-line" id="Name" name="Name" type="text" value="MyWishlist" /> 

Đối Wishitems các 'con' trong bảng, chúng tôi nhận các yếu tố đầu vào được lập chỉ mục:

<input data-val="true" data-val-number="The field Quantity must be a number." data-val-required="The Quantity field is required." name="[0].Quantity" type="text" value="42" /> 
<input name="[0].Name" type="text" value="Unicorns" /> 

Điều này dẫn đến đối số Wishlist wishlist Được đăng lại với thuộc tính trống .Wishitems.

Chữ ký thay thế cho trình xử lý POST ([HttpPost] public ActionResult Edit(Wishlist wishlist, ICollection<Wishitem> wishitems)) vẫn cho tôi số trống wishlist.Wishitems, nhưng cho phép tôi truy cập (có thể sửa đổi) wishitems.

Trong trường hợp thứ hai này, tôi có thể thực hiện một số cho việc ràng buộc tùy chỉnh.Ví dụ (không mã thanh lịch nhất mà tôi đã nhìn thấy trong sự nghiệp của tôi):

[HttpPost] 
public ActionResult Edit(Wishlist editedList, ICollection<Wishitem> editedItems) 
{ 
    var wishlist = db.Wishlists.Find(editedList.WishListId); 
    if (wishlist == null) { return HttpNotFound(); } 

    if (ModelState.IsValid) 
    { 
     UpdateModel(wishlist); 

     foreach (var editedItem in editedItems) 
     { 
      var wishitem = wishlist.Wishitems.Where(wi => wi.WishitemId == editedItem.WishitemId).Single(); 
      if (wishitem != null) 
      { 
       wishitem.Name = editedItem.Name; 
       wishitem.Quantity = editedItem.Quantity; 
      } 
     } 
     db.SaveChanges(); 
     return View(wishlist); 
    } 
    else 
    { 
     editedList.Wishitems = editedItems; 
     return View(editedList); 
    } 
} 

Sản phẩm yêu thích

Tôi muốn có một cách cho tôi để nhận được tất cả các dữ liệu được đăng trong một đối tượng có cấu trúc đơn , ví dụ:

[HttpPost] 
public ActionResult Edit(Wishlist wishlist) { /* ...Save the wishlist... */ } 

với wishlist.Wishitems điền với các mục (có khả năng sửa đổi)

Hoặc một nhiều el cách để tôi xử lý việc hợp nhất dữ liệu, nếu bộ điều khiển của tôi phải nhận riêng chúng. Một cái gì đó như

[HttpPost] 
public ActionResult Edit(Wishlist editedList, ICollection<Wishitem> editedItems) 
{ 
    var wishlist = db.Wishlists.Find(editedList.WishListId); 
    if (wishlist == null) { return HttpNotFound(); } 

    if (ModelState.IsValid) 
    { 
     UpdateModel(wishlist); 
     /* and now wishlist.Wishitems has been updated with the data from the Form (aka: editedItems) */ 
     db.SaveChanges(); 
     return View(wishlist); 
    } 
    /* ...Etc etc... */ 
} 

Gợi ý, mẹo, suy nghĩ?

Ghi chú:

  • Đây là một ví dụ Sandbox. Ứng dụng thực tế tôi đang làm việc khá khác nhau, không liên quan gì đến miền được phơi bày trong Sandbox.
  • Tôi không sử dụng 'Chế độ xem' trong ví dụ, bởi vì - xa - chúng dường như không phải là một phần của câu trả lời. Nếu họ là cần thiết, tôi chắc chắn sẽ giới thiệu họ (và trong ứng dụng thực sự tôi đang làm việc trên chúng tôi đã sử dụng chúng).
  • Tương tự, kho lưu trữ được tóm tắt bởi lớp SandboxDbContext đơn giản trong ví dụ này, nhưng có lẽ sẽ được thay thế bằng một mẫu Repository và Unit Of Work chung trong ứng dụng thực.
  • Ứng dụng Sandbox được xây dựng sử dụng:
    • Visual Web Developer 2010 Express
      • Hotfix cho Microsoft Visual Web Developer 2010 Express - ENU (KB2547352)
      • Hotfix cho Microsoft Visual Web Developer 2010 Express - ENU (KB2548139)
      • Microsoft Visual Web Developer 2010 Express - Gói dịch vụ ENU 1 (KB983509)
    • .NET Framework 4.0.30319 SP1Rel
    • ASP.NET MVC3
      • Razor cú pháp cho Views
      • Code-Đầu tiên tiếp cận
    • Entity Framework 4.2.0.0
  • Sandbox được xây dựng nhắm mục tiêu.NET Framework 4

Tài liệu tham khảo:

  • "Getting Started with ASP.NET MVC3" Covers những điều cơ bản, nhưng không đối phó với các mối quan hệ mô hình

  • "Getting Started with EF using MVC" an-asp-net-MVC-ứng dụng Đặc biệt Part 6 cho biết cách xử lý một số mối quan hệ giữa các mô hình. Tuy nhiên, hướng dẫn này sử dụng đối số FormCollection cho trình xử lý POST của nó, thay vì liên kết mô hình tự động. Nói cách khác: [HttpPost] public ActionResult Chỉnh sửa (int id, FormCollection FormCollection) Thay vì một cái gì đó dọc theo dòng của [HttpPost] public ActionResult Chỉnh sửa (InstructorAndCoursesViewModel ViewModel) Ngoài ra, danh sách các khóa học kết hợp với một giảng viên cho được đại diện (trong giao diện người dùng) như một tập hợp các hộp kiểm có cùng tên (dẫn đến đối số string[] cho trình xử lý POST), không hoàn toàn giống với kịch bản mà tôi đang xem xét.

  • "Editing a variable length list, ASP.NET MVC2-style" Dựa trên MVC2 (vì vậy tôi tự hỏi nếu nó vẫn mô tả tùy chọn tốt nhất hiện nay chúng tôi có MVC3). Phải thừa nhận rằng, tôi chưa (chưa) xử lý việc chèn và/hoặc loại bỏ các mô hình Trẻ em khỏi danh sách. Ngoài ra, giải pháp này:

    • dựa trên mã tùy chỉnh (BeginCollectionItem) - đó là tốt nếu nó là cần thiết (nhưng nó vẫn cần thiết trong MVC3?)
    • xử lý danh sách như một bộ sưu tập miễn phí-đứng, chứ không phải là một thuộc tính của mô hình gói - nói cách khác, có mô hình "GiftsSet" xung quanh (tương đương với mô hình Wishlist cha trong ví dụ của tôi), mặc dù tôi không biết liệu có phải một mô hình cha mẹ rõ ràng đã làm mất hiệu lực giải pháp này hay không. bài
  • "ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries" Scott Hanselman là một trong những con trai của tài liệu tham khảo được trích dẫn nhất chủ đề của ràng buộc vào các danh sách trong các ứng dụng MVC. Tuy nhiên, ông chỉ đơn giản mô tả các quy ước đặt tên được áp dụng bởi khung công tác và được sử dụng để tạo các đối tượng phù hợp với phương thức hành động của bạn (lưu ý cách bài viết không có ví dụ về việc tạo một trang để gửi dữ liệu đến một trong các hành động được mô tả). Đây là thông tin tuyệt vời nếu chúng tôi phải tự mình tạo. Chúng ta phải?

  • "Model Binding To A List" Một tham chiếu hàng đầu khác của Phil Haack. Nó có một số thông tin tương tự như bài viết của Hansleman ở trên, nhưng cũng cho chúng ta thấy chúng ta có thể sử dụng HtmlHelpers trong vòng lặp (for (int i = 0; i < 3; i++) { Html.TextBoxFor(m => m[i].Title) }), hoặc trong một Template Editor (Html.EditorFor(m=>m[i])). Tuy nhiên, bằng cách sử dụng phương pháp này, HTML được tạo bởi Mẫu biên tập sẽ không bao gồm bất kỳ tiền tố cụ thể nào (ví dụ: tên và id của các yếu tố đầu vào sẽ ở dạng [index].FieldName như: [0].Quantity hoặc [1].Name). Điều này có thể hoặc có thể không quan trọng trong ví dụ này, nhưng có thể sẽ là một vấn đề trong ứng dụng thực tế của tôi, trong đó các danh sách trẻ em 'song song' khác nhau có thể xuất hiện trong cùng một chế độ xem.

+0

bạn cần phải đóng khung câu hỏi của bạn mà có thể dễ dàng đọc được – user1006544

Trả lời

1

Bạn có thể muốn kiểm tra liên kết này http://www.codetuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx tôi đã vấn đề tương tự và ở trên cho phép tôi hiểu nó

+0

Cảm ơn bạn đã liên kết. Vì vậy .. Tôi chỉ cần cắn viên đạn và viết chất kết dính tùy chỉnh của riêng tôi sau khi tất cả? Vâng, ít nhất bây giờ tôi biết lý do tại sao các chất kết dính mặc định là không đủ và tôi có thể giữ một mắt trên bất kỳ cập nhật cho nó từ MS. Cảm ơn vì tiền hỗ trợ; Tôi sẽ chờ đợi một chút trước khi chấp nhận câu trả lời mặc dù (muốn xem nếu có ai khác đề nghị lựa chọn thay thế, và tôi muốn thử nó trong ứng dụng Sandbox của tôi ở nhà tối nay). – FOR

+0

vâng, xin vui lòng chờ đợi, tôi cũng quan tâm đến giải pháp. Cho đến nay tôi đã kết thúc việc lặp đi lặp lại trought bộ sưu tập của đối tượng của tôi và đệ trình từng thực thể con một bằng cách sử dụng jQuery $ .post nhưng nó có một số hạn chế – torm

+0

liên kết bị hỏng: ( – TWilly

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