2010-07-29 39 views
128

Tôi là nhà phát triển Java mới với .NET. Tôi đang làm việc trên một dự án .Net MVC2 nơi tôi muốn có một cái nhìn một phần để bọc một widget. Mỗi đối tượng widget JS có một đối tượng dữ liệu JSON sẽ được điền bởi dữ liệu mô hình. Sau đó, phương pháp để cập nhật dữ liệu này ràng buộc với các sự kiện khi dữ liệu được thay đổi trong tiện ích hoặc nếu dữ liệu đó được thay đổi trong tiện ích con khác. Mã là một cái gì đó như thế này.ASP.NET MVC: Cách chuyển đổi Xem mô hình thành đối tượng Json

MyController

virtual public ActionResult DisplaySomeWidget(int id) 
{ 
    SomeModelView returnData = someDataMapper.getbyid(1); 

    return View(myview, returnData); 
} 

myview.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SomeModelView>" %> 

    <script type="text/javascript"> 

     //creates base widget object; 
     var thisWidgetName= new Widget(); 

     thisWidgetName.updateTable= function() { 
      // UpdatesData 
     }; 

      $(document).ready(function() { 
       thisWidgetName.data = <% converttoJSON(model) %> 
       $(document).bind('DATA_CHANGED', thisWidgetName.updateTable()); 
      }); 
     </script> 

    <div><%:model.name%></div> 

Những gì tôi không biết là làm thế nào để gửi dữ liệu qua như SomeModelView và sau đó có thể sử dụng để cư tiện ích cũng như chuyển đổi nó thành Json. Tôi đã có một số cách thực sự đơn giản để làm điều đó trong bộ điều khiển nhưng không phải trong xem. Tôi hình dung đây là câu hỏi cơ bản Tôi đã đi vài giờ để làm cái này.

+1

Tôi biết đây là một câu hỏi cũ. Nhưng đến hôm nay, có nhiều cách tốt hơn để làm điều đó. Không kết hợp nội dòng JSON với kết quả Xem của bạn. JSON dễ dàng được nối tiếp qua AJAX và có thể được xử lý như đối tượng. Mọi thứ trong JavaScript phải tách biệt với Chế độ xem. Bạn có thể dễ dàng trả về các mô hình mà không cần bất kỳ nỗ lực nào thông qua Bộ điều khiển. – ppumkin

Trả lời

296

Trong mvc3 với dao cạo @Html.Raw(Json.Encode(object)) dường như làm điều này.

+1

+1 Tôi đã sử dụng Html.Raw, nhưng không bao giờ tìm thấy Json.Encode và chỉ sử dụng JavaScriptSerializer để thêm chuỗi trong bộ điều khiển vào kiểu xem – AaronLS

+0

Điều đó hoạt động như một sự quyến rũ. Tôi nghĩ rằng nó hoạt động tốt hơn trong quan điểm trong trường hợp nhất định. – PJH

+4

Cách tiếp cận này hoạt động ngay cả khi bạn muốn chuyển JSON kết quả sang Javascript. Dao cạo phàn nàn với các squiggles màu xanh lá cây nếu bạn đặt mã html @ Html.Raw (...) như là một tham số chức năng bên trong các thẻ

4

Bạn có thể sử dụng Json từ hành động trực tiếp,

hành động của bạn sẽ là một cái gì đó như thế này:

virtual public JsonResult DisplaySomeWidget(int id) 
{ 
    SomeModelView returnData = someDataMapper.getbyid(1); 
    return Json(returnData); 
} 

Sửa

Chỉ cần thấy rằng bạn giả định này là Model của một Xem như vậy ở trên là không đúng, bạn sẽ phải thực hiện một cuộc gọi Ajax đến phương pháp điều khiển để có được điều này, các ascx sẽ không sau đó có một mô hình, tôi sẽ để lại mã của tôi chỉ trong trường hợp nó hữu ích cho bạn và bạn có thể sửa đổi cuộc gọi

+1

nhưng anh ta không thể làm điều này trong quan điểm, anh ta phải thực hiện cuộc gọi ajax thứ hai –

+0

@Andrew Bullock vừa chỉnh sửa khi tôi nhận ra – Pharabus

+0

Cảm ơn, ban đầu tôi đã thực hiện việc này bằng cách sử dụng cuộc gọi json của jQuery và đang có kế hoạch về HTML các yếu tố cư trú bản thân từ json. Tuy nhiên, mẫu chúng ta đang theo dõi ngay bây giờ là khung nhìn của chúng ta sẽ trả về một modelView và đó là cách dễ nhất để điền các phần tử HTML cơ bản như bảng vv. Tôi có thể gửi cùng một dữ liệu ở định dạng JSON dưới dạng ViewData nhưng có vẻ như lãng phí. –

28

Thực hiện tốt, bạn chỉ mới bắt đầu sử dụng MVC và bạn đã tìm thấy lỗ hổng.

Bạn thực sự không muốn chuyển đổi nó thành JSON trong chế độ xem và bạn không thực sự muốn chuyển đổi nó trong bộ điều khiển vì không phải vị trí nào trong số này phù hợp. Thật không may, bạn đang mắc kẹt với tình trạng này.

Điều tốt nhất tôi đã tìm thấy để làm là gửi JSON để xem trong một ViewModel, như thế này:

var data = somedata; 
var viewModel = new ViewModel(); 
var serializer = new JavaScriptSerializer(); 
viewModel.JsonData = serializer.Serialize(data); 

return View("viewname", viewModel); 

sau đó sử dụng

<%= Model.JsonData %> 

theo quan điểm của bạn. Hãy nhận biết rằng JavaScript JavaScriptSerializer chuẩn là khá crap.

làm việc đó trong bộ điều khiển ít nhất làm cho nó kiểm chứng (mặc dù không chính xác như trên - có thể bạn muốn có một ISerializer như một sự phụ thuộc, do đó bạn có thể thử nó)

Cập nhật cũng có, liên quan đến JavaScript , nó sẽ được thực hành tốt để quấn ALL widget JS bạn có ở trên như sau:

(
    // all js here 
)(); 

cách này nếu bạn đặt nhiều widget trên một trang, bạn sẽ không nhận các cuộc xung đột (trừ khi bạn cần truy cập vào các phương pháp từ những nơi khác trong trang, nhưng trong trường hợp đó, bạn nên đăng ký tiện ích con th một số khuôn khổ widget anyway).Nó có thể không phải là một vấn đề bây giờ, nhưng nó sẽ là tốt thực hành để thêm các dấu ngoặc bây giờ để tiết kiệm cho mình nỗ lực nhiều trong tương lai khi nó trở thành một yêu cầu, nó cũng thực hành tốt OO để đóng gói các chức năng.

+1

Điều này có vẻ thú vị. Tôi sẽ chỉ tạo một bản sao của dữ liệu dưới dạng json và chuyển nó thành dạng xemData nhưng cách này trông thú vị hơn. Tôi sẽ chơi với điều này và cho bạn biết. BTW đây là lần đầu tiên tôi đăng câu hỏi lên stackoverflow và mất khoảng 0,5 phút để nhận phản hồi tốt, điều đó thật tuyệt vời !! –

+0

Có gì sai với 'JavaScriptSerializer'? –

+0

nothings _wrong_ với nó, nó chỉ không thể tùy chỉnh, nếu bạn muốn bất kỳ định dạng giá trị tùy chỉnh nào bạn phải làm trước khi bàn tay, về cơ bản làm mọi thứ thành chuỗi: (điều này nổi bật nhất với ngày tháng. Tôi biết có cách giải quyết dễ dàng, nhưng không nên –

0

Andrew đã có một phản ứng tuyệt vời nhưng tôi muốn tweek nó một chút. Cách này khác nhau là tôi thích ModelViews của tôi không có dữ liệu trên đầu. Chỉ là dữ liệu cho đối tượng. Có vẻ như ViewData phù hợp với hóa đơn cho dữ liệu trên đầu, nhưng tất nhiên tôi mới ở đây. Tôi đề nghị làm một cái gì đó như thế này.

khiển

virtual public ActionResult DisplaySomeWidget(int id) 
{ 
    SomeModelView returnData = someDataMapper.getbyid(1); 
    var serializer = new JavaScriptSerializer(); 
    ViewData["JSON"] = serializer.Serialize(returnData); 
    return View(myview, returnData); 
} 

Xem

//create base js object; 
var myWidget= new Widget(); //Widget is a class with a public member variable called data. 
myWidget.data= <%= ViewData["JSON"] %>; 

gì này làm cho bạn là nó mang lại cho bạn cùng một dữ liệu trong JSON của bạn như trong ModelView của bạn để bạn có khả năng có thể trả lại JSON trở lại bộ điều khiển của bạn và nó sẽ có tất cả các bộ phận. Điều này tương tự như chỉ yêu cầu nó thông qua một JSONRequest tuy nhiên nó đòi hỏi một cuộc gọi ít hơn để nó giúp bạn tiết kiệm chi phí đó. BTW này là sôi nổi cho ngày nhưng có vẻ như một sợi khác.

18

tôi thấy nó được khá tốt đẹp để làm điều đó như thế này (sử dụng trong giao diện):

@Html.HiddenJsonFor(m => m.TrackingTypes) 

Đây là theo lớp helper phương pháp mở rộng:

public static class DataHelpers 
{ 
    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) 
    { 
     return HiddenJsonFor(htmlHelper, expression, (IDictionary<string, object>) null); 
    } 

    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) 
    { 
     return HiddenJsonFor(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); 
    } 

    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes) 
    { 
     var name = ExpressionHelper.GetExpressionText(expression); 
     var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 

     var tagBuilder = new TagBuilder("input"); 
     tagBuilder.MergeAttributes(htmlAttributes); 
     tagBuilder.MergeAttribute("name", name); 
     tagBuilder.MergeAttribute("type", "hidden"); 

     var json = JsonConvert.SerializeObject(metadata.Model); 

     tagBuilder.MergeAttribute("value", json); 

     return MvcHtmlString.Create(tagBuilder.ToString()); 
    } 
} 

Nó không phải là siêu -sofisticated, nhưng nó giải quyết vấn đề của nơi để đặt nó (trong điều khiển hoặc trong xem?) Câu trả lời rõ ràng là: không;)

+0

Điều này là tốt đẹp và sạch sẽ trong quan điểm của tôi và gói trong một người trợ giúp tái sử dụng. Chúc mừng, J – John

0

Mở rộng câu trả lời lớn từ Dave. Bạn có thể tạo một đơn giản HtmlHelper.

public static IHtmlString RenderAsJson(this HtmlHelper helper, object model) 
{ 
    return helper.Raw(Json.Encode(model)); 
} 

Và theo quan điểm của bạn:

@Html.RenderAsJson(Model) 

Bằng cách này bạn có thể tập trung logic để tạo JSON nếu bạn vì một lý do, muốn thay đổi logic sau.

3

@ Html.Raw (Json.Encode (object)) có thể được sử dụng để chuyển đổi các Object Xem phương thức để JSON

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