ASP.NET MVC:如何将视图模型转换为Json对象

我是Java新的.NET开发者。 我正在一个.Net MVC2项目,我想有一个局部视图来包装一个小部件。 每个JS小部件对象都有一个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> 

我不知道的是如何通过SomeModelView发送数据,然后能够使用它来填充小部件,并将其转换为Json。 我似乎有一些真正简单的方法在控制器中完成,而不是在视图中。 我想这是一个基本的问题,我已经花了几个小时试图做出这个光华。

在mvc3与剃刀@Html.Raw(Json.Encode(object))似乎做的伎俩。

干得好,你刚开始使用MVC,你已经发现了它的第一个重大缺陷。

你真的不想在视图中把它转换成JSON,而且你也不想在控制器中转换它,因为这些位置都没有意义。 不幸的是,你陷入了这种情况。

我发现要做的最好的事情是将JSON发送到ViewModel中的视图,如下所示:

 var data = somedata; var viewModel = new ViewModel(); var serializer = new JavaScriptSerializer(); viewModel.JsonData = serializer.Serialize(data); return View("viewname", viewModel); 

然后使用

 <%= Model.JsonData %> 

在你看来。 请注意,标准的.NET JavaScriptSerializer是相当糟糕的。

在控制器中做它至less使它可testing(虽然不完全像上面 – 你可能想要一个ISerializer作为依赖,所以你可以嘲笑它)

更新也关于你的JavaScript,这是一个很好的习惯,把上面所有的小部件JS包装起来,例如:

 ( // all js here )(); 

这样,如果你在一个页面上放置多个小部件,你就不会发生冲突(除非你需要从页面的其他地方访问这些方法,但是在这种情况下,你应该使用一些小部件框架来注册这个小部件)。 现在可能不是什么问题,但现在增加括号是为了在将来成为一个需求时节省自己的努力,这是一个很好的习惯,封装function也是很好的OO实践。

我发现这样做很好(在视图中使用):

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

这里是相应的帮助方法扩展类:

 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()); } } 

它不是超级复杂的,但它解决了把它放在哪里的问题(在Controller中还是在视图中?)答案显然是:既不;)

你可以直接使用Json

你的行为将是这样的:

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

编辑

只是看到你认为这是一个视图Model ,所以上述不是严格正确的,你将不得不作出一个Ajax调用控制器方法来获得这个, ascx不会有一个模型本身,我会留下我的代码,以防万一它对你有用,你可以修改通话

@ Html.Raw(Json.Encode(object))可用于将视图模态对象转换为JSON

 <htmltag id='elementId' data-ZZZZ'='@Html.Raw(Json.Encode(Model))' /> 

请参阅https://highspeedlowdrag.wordpress.com/2014/08/23/mvc-data-to-jquery-data/

我做了下面,它的作品像魅力。

<input id="hdnElement" class="hdnElement" type="hidden" value='@Html.Raw(Json.Encode(Model))'>

从戴夫延伸的伟大答案。 你可以创build一个简单的HtmlHelper 。

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

在你看来:

 @Html.RenderAsJson(Model) 

这样,如果您出于某种原因希望稍后更改逻辑,则可以集中创buildJSON的逻辑。

安德鲁有很好的回应,但我想稍微微调一下。 这是不同的方式是我喜欢我的ModelViews没有开销数据。 只是对象的数据。 ViewData似乎适合头顶数据的账单,但我当然是新手。 我build议做这样的事情。

调节器

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

视图

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

它为你做了什么,它会为你提供与你的ModelView相同的数据,所以你可以将JSON返回给你的控制器,它将包含所有的部分。 这与通过JSONRequest请求它类似,但它需要less一个呼叫,所以它可以节省您的开销。 顺便说一句,这是date时髦,但似乎是另一个线程。