2013-09-06 40 views
13

Tôi đang giới thiệu KnockoutJS vào một ứng dụng hiện có. Kế hoạch của tôi là sửa đổi/sử dụng các khung nhìn từng phần hiện có mà chúng ta đã tạo và liên kết chúng với các mô hình khung nhìn JS với các thuộc tính khai báo của Knockout. Khi tôi thực hiện lời gọi AJAX đến một hành động, lý tưởng là tôi muốn hành động trả về cả HTML của chế độ xem một phần và đối tượng JSON. Sau đó, tôi có thể điền vào một div với HTML, chuyển đổi JSON thành một đối tượng Knockout và liên kết nó với HTML. Nhưng tôi không thể tìm ra cách để trả lại cả hai từ hành động.Trả lại một phần Xem và JSON từ ASP.NET MVC Action

Tôi cần kiểu xem đầy đủ vì tôi sẽ cập nhật và cuối cùng gửi lại máy chủ.

Tôi nghĩ về việc có hành động trả về một phần xem (đã được ràng buộc với mô hình), và trong chế độ xem một phần, bao gồm javascript để chuyển đổi mô hình .Net thành đối tượng Knockout. Nhưng tôi cảm thấy rằng việc phân tán JS xung quanh như thế là lộn xộn và không thể duy trì được. Tôi muốn có mọi thứ gần với cuộc gọi ajax ban đầu.

Tôi đoán một cách khác là thực hiện hai cuộc gọi hành động. Một cho JSON và một cho chế độ xem một phần. Nhưng phải có một cách trơn tru.

Bất kỳ ý tưởng nào về cách tốt nhất để thực hiện việc này?

Trả lời

21

Tôi chắc chắn có nhiều cách để thực hiện việc này. Tôi tự hiển thị khung nhìn từ bộ điều khiển, và sau đó chuyển giao diện được hiển thị trở lại như một phần của phản hồi JSON của tôi.

Điều này bảo toàn trách nhiệm của từng pháp nhân. Chế độ xem vẫn được đặt bằng cách sử dụng công cụ xem và chúng có thể được sử dụng lại. Bộ điều khiển biết rất ít hoặc không có gì về khung nhìn ngoài tên và kiểu mô hình của nó.

Manual Rendering

public static class RenderHelper 
{ 
    public static string PartialView(Controller controller, string viewName, object model) 
    { 
     controller.ViewData.Model = model; 

     using(var sw = new StringWriter()) 
     { 
      var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); 
      var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw); 

      viewResult.View.Render(viewContext, sw); 
      viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View); 

      return sw.ToString(); 
     } 
    } 
} 

Trong phương pháp hành động của bạn:

object model = null; // whatever you want 
var obj = new { 
    someOtherProperty = "hello", 
    view = RenderHelper.PartialView(this, "_PartialName", model) 
}; 

return Json(obj); 

Lưu ý rằng tôi đang trở về một loại vô danh. Bạn có thể trả về bất kỳ loại (serializable) nào bạn muốn, miễn là nó có một thuộc tính chuỗi cho khung nhìn được hiển thị.

Kiểm tra

Thử nghiệm hành động sử dụng hiển thị thủ công yêu cầu sửa đổi nhỏ. Điều này là do hiển thị khung nhìn sớm hơn một chút so với nó sẽ được hiển thị trong đường ống MVC.

Manual Rendering

  1. Nhập phương pháp hành động
  2. Render view rõ ràng < - điều này sẽ làm cho nó khó khăn để kiểm tra hành động kêu gọi
  3. Exit phương pháp hành động

tự động Hiển thị

  1. Nhập phương pháp hành động
  2. Tạo một kết quả xem
  3. Exit phương pháp hành động
  4. kết quả Process view (do đó vẽ các view)

Nói cách khác, quá trình vẽ thủ công của chúng tôi khởi động một nhiều hoạt động khác gây khó khăn cho việc kiểm tra (chẳng hạn như tương tác với trình quản lý xây dựng để biên dịch chế độ xem).

Giả sử bạn muốn thử nghiệm phương thức hành động chứ không phải nội dung thực tế của chế độ xem, bạn có thể kiểm tra xem mã có đang thực thi trong môi trường được lưu trữ hay không.

public static string PartialView(Controller controller, string viewName, object model) 
    { 
     // returns false from a VS 2013 unit test, true from IIS 
     if(!HostingEnvironment.IsHosted) 
     { 
      // return whatever you want here 
      return string.Empty; 
     } 

     // continue as usual 
    } 

Kiểm tra HostingEnvironment.IsHosted không đắt tiền (dưới mui xe, nó chỉ đơn giản là một kiểm tra trống).

+0

+1 Không bao giờ nghĩ về một lớp trợ giúp. Đây có thể là giải pháp thanh lịch nhất. Tôi sẽ thử. Cảm ơn. – nthpixel

+0

Bạn không muốn làm: 'var obj = new {view = RenderHelper.PartialView (this," _PartialName ", viewModel), model = koViewModel};'? Hay đó là 'foo' là gì? Hay tôi đang thiếu một cái gì đó? – nwayve

+0

@ Dennis - vâng, "foo" đại diện cho bất kỳ dữ liệu nào khác mà bạn cần trả lại. Tôi không chắc chắn chính xác những gì Knockout cần trên máy khách, nhưng khung nhìn cũng cần một mô hình (ngay cả khi nó là null). –

1

Bạn có thể tạo một <input> ẩn một phần với giá trị được đặt thành chuỗi JSON của ViewModel. Sau đó, trước khi bạn hiển thị chế độ xem từng phần, hãy lấy giá trị JSON từ trường đó và phân tích cú pháp đó. Sau đó, xóa nó khỏi chế độ xem một phần, chèn nó vào trang của bạn, và làm ko.applyBindingsToDescendants(viewModel, $("#parentElement")[0])

Tôi không hoàn toàn chắc chắn về cách tôi cảm nhận về cách tiếp cận này, và nó chỉ là một lý thuyết. Tôi đã không thử nghiệm này ra nhưng tôi nghi ngờ nó sẽ làm việc. Một booty trap bạn phải tìm kiếm là trình duyệt đang cố gắng lưu trữ yêu cầu GET của bạn. Trong yêu cầu ajax bạn muốn thực hiện:

$.ajax({ 
    url: "/", 
    type: 'GET', 
    cache: 'false' 
}); 

Hoặc chỉ cần yêu cầu $.post. (reference)

Vì vậy, đó là một tùy chọn.

+0

+1 cho tùy chọn ... nhưng tôi cũng không chắc chắn về cảm giác của mình về nó. – nthpixel

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