ASP.NET MVC:如何将View Model转换为Json对象

Chr*_*ens 153 .net javascript asp.net-mvc json

我是.NET新手的Java开发人员.我正在开发.Net MVC2项目,我希望有一个局部视图来包装一个小部件.每个JS小部件对象都有一个JSON数据对象,该对象将由模型数据填充.然后,更新此数据的方法绑定到在窗口小部件中更改数据时的事件,或者如果在另一个窗口小部件中更改了该数据.代码是这样的.

myController的

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

  return View(myview, returnData);
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*ave 338

在mvc3用剃刀@Html.Raw(Json.Encode(object))似乎可以做到这一点.

  • 当使用MVC 6(也许是5)时,你需要使用`Json.Serialize`而不是Encode. (12认同)
  • 即使您希望将生成的JSON传递给Javascript,此方法也可以使用.如果你将@Html.Raw(...)代码作为函数参数放在<script>标签内,Razor会抱怨绿色波形,但是JSON确实会让它被调用.非常方便和光滑.+1 (5认同)
  • _Json.Encode_将我的二维数组编码为json中的一维数组._Newtonsoft.Json.JsonConvert.SerializeObject_将两个维度正确地序列化为json.所以我建议使用后者. (3认同)
  • +1我使用了Html.Raw,但从未找到Json.Encode,只是使用JavaScriptSerializer将控制器中的字符串添加到视图模型中 (2认同)

And*_*ock 31

干得好,你刚刚开始使用MVC,你发现了它的第一个主要缺陷.

你真的不想在视图中将它转换为JSON,并且你真的不想在控制器中转换它,因为这些位置都没有意义.不幸的是,你遇到了这种情况.

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

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

return View("viewname", viewModel);
Run Code Online (Sandbox Code Playgroud)

然后用

<%= Model.JsonData %>
Run Code Online (Sandbox Code Playgroud)

在你看来.请注意,标准的.NET JavaScriptSerializer非常糟糕.

在控制器中执行此操作至少使其可测试(尽管不完全像上面那样 - 您可能希望将ISerializer作为依赖项,以便您可以模拟它)

更新,关于你的JavaScript,最好包装你上面的所有小部件JS,如下所示:

(
    // all js here
)();
Run Code Online (Sandbox Code Playgroud)

这样,如果你在页面上放置多个小部件,你就不会遇到冲突(除非你需要从页面的其他地方访问这些方法,但在这种情况下你应该用一些小部件框架注册小部件).它现在可能不是一个问题,但是现在添加括号以便在将来成为一项要求时节省大量工作将是一个好习惯,它也是封装功能的良好OO实践.

  • 我撤回了我先前的陈述"它没有错".它有什么不妥之处. (2认同)

小智 18

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

    @Html.HiddenJsonFor(m => m.TrackingTypes)
Run Code Online (Sandbox Code Playgroud)

这是相应的辅助方法Extension类:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

它不是超级软化的,但是它解决了把它放在哪里的问题(在Controller中或在视图中?)答案很明显:既不是;)


Pha*_*bus 6

您可以Json直接从操作中使用,

您的操作将如下所示:

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

编辑

刚刚看到您假设这是Model一个View的视图,因此以上内容并非严格正确,您将必须Ajax调用controller方法来获取此信息,ascx然后再没有模型本身,我将保留我的代码以防万一对您有用,您可以修改通话

  • 您不应该将JSON嵌入到View Result中。OP要么需要遵循实践的标准MVC并返回模型或视图模型,要么执行AJAX。在视图中嵌入JSON绝对没有理由。那只是很脏的代码。此答案是正确的方法,也是Microsoft实践推荐的方法。否决票是不必要的,这绝对是正确的答案。我们不应该鼓励不良的编码习惯。通过AJAX的JSON或通过视图的模型。没有人喜欢带有混合标记的意大利面条代码! (2认同)