2012-02-09 18 views
5

Trong chế độ xem của tôi, tôi có danh sách các mục tôi tìm nạp từ cơ sở dữ liệu và sau đó gửi đến chế độ xem. Tôi muốn biết nếu nó có thể tránh phải nạp tiền các tài sản tùy chọn bất cứ khi nào tôi nhấn một hành động bài và cần phải trả lại mô hình (cho lỗi xác nhận và những gì không)?Sử dụng lại dữ liệu mô hình trong một hành động sau

Trong biểu mẫu web, điều này sẽ không cần thiết.

Chỉnh sửa: Tôi không rõ ràng. Vấn đề của tôi là với các tùy chọn SelectList tôi sử dụng cho DropDownLists của tôi. Tất cả mọi thứ được đăng, nhưng nếu tôi phải quay trở lại xem (mô hình không hợp lệ), tôi phải tải lại các tùy chọn từ cơ sở dữ liệu! Tôi muốn biết nếu điều này có thể tránh được.

viewmodel của tôi:

public class TestModel 
{ 
    public TestModel() 
    { 
     Departments = new List<SelectListItem>(); 
    } 

    public string Name { get; set; } 
    public int Department { get; set; } 
    public IEnumerable<SelectListItem> Departments { get; set; } 
} 

Quan điểm của tôi:

@model MvcApplication1.Models.TestModel  
@using (Html.BeginForm()) 
{ 
    @Html.TextBoxFor(m => m.Name) 

    @Html.DropDownListFor(m => m.Department, Model.Departments) 

    <input type=submit value=Submit /> 
} 

điều khiển của tôi (đừng để ý những nhận xét trên HttpPost):

public ActionResult Index() 
{ 
    TestModel model = new TestModel 
    { 
     Name = "Rafael", 
     Department = 1, 
     Departments = new List<SelectListItem> 
     { 
      new SelectListItem { Text = "Sales", Value = "1" }, 
      new SelectListItem { Text = "Marketing", Value = "2", Selected = true }, 
      new SelectListItem { Text = "Development", Value = "3" } 
     } 
    }; 

    // Departments gets filled from a database. 

    return View(model); 
} 

[HttpPost] 
public ActionResult Index(TestModel model) 
{ 
if (!ModelState.IsValid) 
{ 
    //Do I have to fill model.Departments again!?!?!? 

    return View(model); 
} 
else { ... } 
} 

Cảm ơn trước.

Chỉnh sửa: FYI, giải pháp của tôi là sử dụng biến số Session.

Trả lời

1

Chỉ cần mạnh mẽ nhập chế độ xem của bạn và thay đổi phương thức điều khiển của bạn để có thông số của loại lớp đó.

Đó là, quan điểm

@model MyNamesspace.Models.MyModel 
... 
@using (Html.BeginForm()) 
{ 
    .... 
} 

Và bạn điều khiển phương pháp được đưa lên.

[HttpPost] 
public ActionResult MyAction(MyModel model) 
{ 
    ... 
} 

EDIT: Cũng đảm bảo bạn có trường biểu mẫu cho mỗi thuộc tính của mô hình mà bạn cần được đăng lên bộ điều khiển. Ví dụ của tôi là sử dụng Razor quá BTW.

+0

Chăm sóc để xem chỉnh sửa của tôi? – rebelliard

+0

OK Tôi hiểu ý của bạn bây giờ. Tôi đã gặp vấn đề tương tự với dự án cuối cùng của tôi. Thật không may, sử dụng một bài đăng HTTP vốn sẽ giới hạn mô hình của bạn thành tương đương với các cặp khóa-giá trị. Tức là, bạn không thể có một mô hình phức tạp với nhiều đối tượng nghiệp vụ hơn khi các thuộc tính được trả về cho bộ điều khiển. Vì vậy, bạn sẽ phải lưu trữ danh sách các phòng ban ở đâu đó liên tục. Phiên sẽ thích hợp cho điều này, miễn là bạn xóa nó khi bạn đã hoàn tất. Nếu bạn thực sự, thực sự cần phải gửi các đối tượng qua dây, bạn cần phải sử dụng JSON hoặc một số kỹ thuật tuần tự hóa khác. – jhsowter

+0

Tôi hiểu. Bạn có đề nghị chuyển dữ liệu trở lại từ một JSON bên trong một đầu vào bị ẩn hoặc một đối tượng Session [] không? Cảm ơn. – rebelliard

0

Tôi gặp phải sự cố tương tự khi cố gắng tạo thuật sĩ Order trong MVC (nơi mỗi trang của trình hướng dẫn được triển khai dưới dạng chế độ xem một phần được tải bởi AJAX). Tôi rất nghi ngờ nó là gợi ý phương pháp nhưng cách tôi giải quyết này là để gọi một phương thức tùy chỉnh MergeChanges trong mỗi hành động được gọi bằng thuật sĩ của tôi:

public Order MergeChanges(Order newOrder) 
{ 
    var sessionHistory = (List<string>)Session["sessionHistory"]; 

    if (sessionHistory == null || sessionHistory.Count == 0) 
    return MergeChanges(newOrder, -1); 

    return MergeChanges(newOrder, MasterViewController.GetStepNumberByName(sessionHistory.Last())); 
} 

public Order MergeChanges(Order newOrder, int step) 
{ 
    PreMerge(newOrder); 

    Order result = null; 
    try 
    { 
     ApplyLookups(ref newOrder); 
     Order oldOrder = (Order)Session["order"]; 

     if (oldOrder == null) 
     { 
      Session["order"] = newOrder; 
      result = newOrder; 
     } 
     else 
     { 
      List<TypeHelper.DecoratedProperty<ModelPageAttribute>> props = null; 
      newOrder.GetType().GetDecoratedProperty<ModelPageAttribute>(ref props); 
      props = props.Where(p => (p.Attributes.Count() > 0 && p.Attributes.First().PageNumber.Contains(step))).ToList(); 
      foreach (var propPair in props) 
      { 
       object oldObj = oldOrder; 
       object newObj = newOrder; 
       if (!string.IsNullOrEmpty(propPair.PropertyPath)) 
       { 
        bool badProp = false; 
        foreach (string propStr in propPair.PropertyPath.Split('\\')) 
        { 
         var prop = oldObj.GetType().GetProperty(propStr); 
         if (prop == null) 
         { 
          badProp = true; 
          break; 
         } 

         oldObj = prop.GetValue(oldObj, BindingFlags.GetProperty, null, null, null); 
         newObj = prop.GetValue(newObj, BindingFlags.GetProperty, null, null, null); 
        } 
        if (badProp) 
          continue; 
       } 

       if (newObj == null) 
        continue; 

       var srcVal = propPair.Property.GetValue(newObj, BindingFlags.GetProperty, null, null, null); 
       var dstVal = propPair.Property.GetValue(oldObj, BindingFlags.GetProperty, null, null, null); 

        var mergeHelperAttr = propPair.Property.GetAttribute<MergeHelperAttribute>(); 
        if (mergeHelperAttr == null) 
        { 
         if (newObj != null) 
          propPair.Property.SetValue(oldObj, srcVal, BindingFlags.SetProperty, null, null, null); 
        } 
        else 
        { 
         var mergeHelper = (IMergeHelper)Activator.CreateInstance(mergeHelperAttr.HelperType); 
         if (mergeHelper == null) 
          continue; 

         mergeHelper.Merge(context, HttpContext.Request, newObj, propPair.Property, srcVal, oldObj, propPair.Property, dstVal); 
        } 
       } 
       result = oldOrder; 
      } 
    } 
    finally 
    { 
    PostMerge(result); 
    } 
    return result; 
} 

Kể từ trường hợp của tôi đã làm điều này với một thuật sĩ, chỉ cụ thể các giá trị được áp dụng cho mỗi trang để chỉ tài khoản cho các thuộc tính được biết đến trang hiện tại của trình hướng dẫn, tôi đã triển khai một số thuộc tính, một lớp (thừa nhận là phức tạp) ViewController và lớp xác thực tùy chỉnh. Tôi có thể chia sẻ một số mã nhiều hơn nhưng mã trên không làm việc grunt nếu bạn không ở trong một tình huống phức tạp như vậy. Nếu có một cách tốt hơn, tôi hy vọng sẽ tìm hiểu nó từ các câu trả lời cho câu hỏi này bởi vì đây là một PITA.

+0

Chà. Tôi đánh giá cao câu trả lời của bạn. Tôi đã bắt đầu suy nghĩ về việc lưu các giá trị trong hiddens trong JSON và sau đó đọc ra khỏi chúng. Có suy nghĩ gì không? – rebelliard

+0

Tùy thuộc vào yêu cầu của ứng dụng web có thể hoạt động. Nó cảm thấy thực sự bẩn mặc dù và nếu bạn có một bộ lớn các lĩnh vực này có thể nặng. Nó có lẽ sẽ làm việc mặc dù. Trong trường hợp của tôi, tôi đã có hơn 150 trường động phức tạp được tính toán nên nó không thực sự là một lựa chọn. Tôi hy vọng bạn sẽ tìm thấy một giải pháp tốt hơn. –

0

Tôi ngạc nhiên khi câu hỏi này không xuất hiện thường xuyên hơn, và tôi cũng ngạc nhiên khi câu trả lời rõ ràng (IMHO) không phải là thực hành tiêu chuẩn trong những ngày này: gần như tất cả các POST phải dựa trên Ajax.Điều này giải quyết toàn bộ vấn đề bao gồm

  1. Không cần phải điền lại dữ liệu biểu mẫu khi bạn có, ví dụ: lỗi xác thực hoặc lỗi ứng dụng (ngoại lệ). Điều này đặc biệt mong muốn khi bạn có trạng thái phía máy khách (trong thời trang ứng dụng web phong phú thực sự).
  2. Không bắt buộc phải thực hiện xác thực phía máy khách. Xác thực có thể là 100% phía máy chủ (trong đó phải là là mọi cách) và trải nghiệm người dùng gần như giống nhau.

Tất nhiên, có một số công việc ban đầu bạn cần làm để xây dựng một khung công tác cho điều này, ví dụ, tôi có một bộ AjaxUpdate, AjaxNothing, AjaxRedirect, AjaxErrors ... ActionResult loại kết xuất Json được xử lý bởi một số Javascript tùy chỉnh. Nhưng một khi bạn nhận được rằng tại chỗ, đó là thuyền trơn tru.

+0

'Xác nhận có thể là 100% phía máy chủ (nơi nó phải là anyways)', tôi đã theo ấn tượng rằng MS đã nghiêng về phía * hơn * xác nhận phía khách hàng bằng cách đẩy công cụ 'DataAnnotation'. Cấp tôi đã không dành đủ thời gian trong lĩnh vực này để thực sự hiểu những gì đang xảy ra, nhưng tất cả các hướng dẫn bạn tìm thấy trên MVC3 và xác nhận dường như đẩy cho phương pháp "Unobtrustive Javascript"/DataAnnotation. Tui bỏ lỡ điều gì vậy? –

+0

@ M.Babcock - Tôi nghĩ MS đang cố gắng làm gì với DataAnnotations và "Unobtrusive Javascript" là giải quyết vấn đề xác nhận phía máy khách và phía máy chủ với cách tiếp cận khác: định cấu hình DataAnnotations và khung sẽ thực hiện * cả xác thực phía máy chủ và phía máy khách một cách minh bạch, nhưng trong mọi trường hợp, xác thực phía máy chủ đều có thẩm quyền và xác thực phía máy khách chỉ dành cho trải nghiệm người dùng. Tuy nhiên, giải pháp của tôi loại bỏ hoàn toàn vấn đề (một vấn đề mà tôi đang tuyên bố đã bị lỗi thời). –

+0

@M.Babcock - Lưu ý rằng tôi vẫn sử dụng DataAnnotations (vâng, tôi đã thích FluentValidation gần đây), nhưng tôi thực hiện xác thực phía máy chủ và trả về các lỗi với một phản hồi AjaxErrors Json được trả lại bằng Javascript bằng cách gọi lại Ajax onsuccess. –

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