2009-09-24 18 views
19

Tôi sử dụng ASP.NET MVC với jQuery và có rất nhiều yêu cầu Ajax cho bộ điều khiển của tôi.Xem một phần so với Json (hoặc cả hai)

Sử dụng chế độ xem một phần (liên kết người dùng) để xây dựng chế độ xem trực tiếp khi trang được tải. Sau đó, nếu tôi cần phải thêm/thay thế dữ liệu dựa trên yêu cầu Ajax của tôi, tôi xây dựng HTML từ phản hồi Json.

Cách tiếp cận này cho phép tôi kiểm soát hoàn toàn, ví dụ: Tôi có thể nhận thêm thông tin từ bộ điều khiển của mình nếu có sự cố và sau đó hiển thị thông báo lỗi dựa trên đó.

Tuy nhiên, gần đây tôi đã thực sự bực mình với tất cả các công việc phụ mà đi vào việc duy trì cấu trúc HTML cả trong quan điểm từng phần của tôi và phần tạo HTML từ Json.

Tôi thích thực hiện yêu cầu jQuery ajax và sau đó có bộ điều khiển trả về PartialView ("mypartialview") và sau đó chỉ cần sử dụng jQuery để thay thế cho HTML trong chế độ xem.

Tuy nhiên, bằng cách này tôi không thể đính kèm dữ liệu bổ sung từ bộ điều khiển - đó là bất kể chế độ xem một phần nào cho tôi - hoặc không có gì. Ít nhất đó là sự hiện diện của tôi trên đó.

Nếu một số xác nhận sai ở một số điểm trong hành động điều khiển của tôi, tôi không muốn trả lại HTML của chế độ xem từng phần.

Vậy làm thế nào để bạn xử lý vấn đề này?

Cảm ơn bạn đã đọc.

Trả lời

2

Tôi tin rằng bạn có thể trả lại html được hiển thị dưới dạng chuỗi - đây có thể là chuỗi html có chứa thông báo lỗi hiển thị?

+1

Thật vậy, đó chỉ là phản hồi của PartialView. Và mặc dù bạn không hoàn toàn đánh vần nó, đây là giải pháp: Có các phương thức AJAX của bạn trả về một PartialView được trả về bằng cách sử dụng cùng một điều khiển người dùng mà bạn đã sử dụng để hiển thị phần đó của trang ban đầu. Bạn làm điều này bằng cách viết trả về PartialView (model) thay vì trả về Json (model). –

+0

Cảm ơn. Đó thực sự là một lời giải thích tốt hơn :) – Paddy

+0

Craig, đó là những gì tôi làm bây giờ. Vấn đề của tôi là tôi muốn trả về cả Html và Json - hoặc để đặt cách khác: Tôi muốn html kết quả được trả về từ PartialView và sau đó bọc trong Json, để tôi có thể gửi cùng với dữ liệu khác. Loại như anh chàng này: http://stackoverflow.com/questions/1168791/returning-a-rentered-html-partial-in-a-json-property-in-asp-net-mvc Tôi đoán ở trên sẽ làm việc, nhưng tôi muốn biết làm thế nào những người khác xử lý này. – bgeek

18

Dựa trên this lưu trữ ngăn xếp anwser Tôi vừa mới bắt đầu thực hiện tương tự.

Trước tiên hãy tạo một phương thức mở rộng cho lớp bộ điều khiển.

public static string RenderViewToString(this Controller controller, string viewName, object model) 
{ 
    using (var writer = new StringWriter()) 
    { 
     var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); 
     controller.ViewData.Model = model; 
     var viewCxt = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, writer); 
     viewCxt.View.Render(viewCxt, writer); 
     return writer.ToString(); 
    } 
} 

Sau đó trả lại json trong phương thức hành động của bộ điều khiển.

return Json(new 
          { 
           Html = this.RenderViewToString("MyView", model), 
           SomeExtraData = data 
          }); 

Yêu cầu ajax của bạn giờ đây sẽ nhận được json có chứa html trong đó. Vẫn đang thử nghiệm cách tiếp cận này để trả về các đoạn Html thuần túy.

Hy vọng điều đó sẽ hữu ích.

EDIT cập nhật để làm việc với dao cạo

4

Dưới đây là một cách để tận dụng lợi thế của Content-Type trả về bởi mỗi kết quả tương ứng. Chúng tôi đang sử dụng điều này để gửi lại thông tin lỗi và đã có sẵn JS để hiển thị thông báo, vì vậy chúng tôi có thể xem một phần thông tin chúng tôi muốn hoặc kiểm soát thông tin để báo cáo lỗi v.v.

Để tham khảo, một phần xem trả lại text/html và phản hồi JSON phải trả lại application/json.

Như thường lệ, phần thú vị ở bên javascript và JQuery ajax() không làm bạn thất vọng!

Trong bộ điều khiển của bạn, chỉ cần trả lại PartialView() hoặc Json(model,) khi thích hợp; chúng tôi đang sử dụng nó ở định dạng try/catch.

public ActionResult Edit(int id) { 
    try { 
     var model = getYourModel(); 
     return PartialView("Edit", model); 
    } 
    catch (Exception ex) { 
     var mi = new MessageInfo(MessageType.Error, String.Format("Edit failed: {0}", ex.Message), true); 
     return Json(mi, "application/json", JsonRequestBehavior.AllowGet); 
    } 
} 

Ở phía JS, chúng tôi đang sử dụng chức năng sau. Lưu ý rằng bạn cần phải thiết lập lại bất kỳ sự kiện JQuery nào bạn đã ghép nối trong $(document).ready() từ GET cấp trang ban đầu, vì vậy chúng tôi có tham số gọi lại.

function getPartialView(action, controller, model, divId, callback) { 
    var url = "/" + controller + "/" + action + "/"; 
    $.ajax({ 
     type: "GET", 
     url: url, 
     data: model, 
     success: function (data, textStatus, jqXHR) { 
      var ct = jqXHR.getResponseHeader("Content-Type"); 
      var mx = ct.match("text\/html"); 
      if (mx != null) { 
       $(divId).html(data); 
       if (callback) { 
        callback($(divId)); 
       } 
      } 
      else { 
       addMessage(data.type, data.title, data.text, data.sticky); 
      } 
     }, 
     error: function (jqXHR, textStatus, errorThrown) { 
      addMessage(3, "\"" + url + "\": Failed", textStatus + ": " + errorThrown, false); 
     } 
    }); 
} 

Các chút khôn lanh chỉ được kiểm tra Content-Type tiêu đề trong câu trả lời, và hành xử cho phù hợp. Xin lưu ý rằng chúng tôi "lừa dối" bằng cách giả sử JSON nếu đó không phải là HTML. Chúng tôi đang gọi chức năng addMessage() có sẵn của chúng tôi, làm bất cứ điều gì bạn cần!

Và cuối cùng, đây là phần tử Anchor mẫu có onclick nhắm mục tiêu getPartialView() ở trên.

<a href="#" onclick="getPartialView('Action', 'Controller', model, '#partialviewdivid', function(dvx) { connectJqueryEvents(dvx); })">Cancel</a> 

trình vĩ đại ...

Trừ hình thức nộp qua Ajax.BeginForm() nơi payload JSON được điều trị nhầm lẫn dưới dạng HTML do thiếu xác nhận của Content-Type. Kết quả là div của bạn được thêm một số JSON vào nó, về cơ bản không hiển thị dưới dạng HTML. Gọi lại AjaxOptions.OnSuccess không thực thi, nhưng đã quá muộn cho DOM của bạn tại thời điểm đó!

Có một giải pháp đơn giản, nhưng rất tiếc, giải pháp này yêu cầu sửa chữa nhỏ đến jquery-unobtrusive-ajax.js vì chức năng asyncOnSuccess() bị thiếu tầm nhìn như được viết.

function asyncOnSuccess(element, data, contentType) { 
    var mode; 

    if (contentType.indexOf("application/x-javascript") !== -1) { 
    return; 
    } 
    if (contentType.indexOf("application/json") !== -1) { 
    return; 
    } 
...snip... 
} 

Trong phiên bản OOTB, câu hỏi thứ hai if bị thiếu; thêm vào đó là sửa chữa cần thiết để giữ cho nó không bị đóng tải trọng tải JSON của bạn vào DOM.

Với sửa lỗi này tại chỗ, tải trọng JSON chuyển vào AjaxOptions.OnSuccess Javascript của bạn và bạn có thể tiến hành nếu cần.

Có Bạn có thể Get Cả

Hy vọng rằng bạn biết kể từ khi bạn đang gửi Json, bạn có thể gửi lại bất kỳ loại mô hình, và để cho các Javascript sắp xếp nó ra; hasOwnProperty() có ích ở đó. Vì vậy, rõ ràng là bạn có thể gửi lại một số HTML xem qua đã được đề cập đến RenderViewToString().

0

Bạn cũng có thể làm theo cách này, Đặt bộ điều khiển này Bên trong bộ điều khiển của bạn.

protected string RenderPartialViewToString(string viewName, object model) 
{ 
    if (string.IsNullOrEmpty(viewName)) 
     viewName = ControllerContext.RouteData.GetRequiredString("action"); 

    ViewData.Model = model; 

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

     return sw.GetStringBuilder().ToString(); 
    } 
} 
Các vấn đề liên quan