如何在 ASP.NET MVC 中将视图模型转换为 JSON 对象?

IT技术 .net javascript asp.net-mvc json
2021-01-30 11:42:24

我是一名 Java 开发人员,刚接触 .NET。我正在处理一个 .NET MVC2 项目,我想在其中使用局部视图来包装小部件。每个 JavaScript 小部件对象都有一个 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>

我不知道如何将数据发送到 asSomeModelView然后能够使用它来填充小部件并将其转换为 JSON。我在控制器中看到了一些非常简单的方法,但在视图中却没有。我认为这是一个基本问题,但我已经花了几个小时试图使这个问题变得光滑。

6个回答

在带有剃刀的 mvc3 中@Html.Raw(Json.Encode(object))似乎可以解决问题。

Json.Encode将我的二维数组编码为 json 中的一维数组。Newtonsoft.Json.JsonConvert.SerializeObject将两个维度正确序列化为 json。所以我建议使用后一种。
2021-03-26 11:42:24
这是自 MVC3 以来的做法,应该从控制器返回。不要将 json 嵌入到您的 Viewresult 中。而是让控制器单独处理 JSON 并通过 AJAX 执行 JSON 请求。如果您在视图上需要 JSON,那么您就做错了。使用 ViewModel 或其他东西。
2021-03-29 11:42:24
即使您想将生成的 JSON 传递给 Javascript,这种方法也有效。如果您将 @Html.Raw(...) 代码作为函数参数放在 <script> 标签内,Razor 会抱怨绿色波浪线,但 JSON 确实可以到达被调用的 JS。非常方便和光滑。+1
2021-04-03 11:42:24
使用 MVC 6(也可能是 5)时,您需要使用Json.Serialize而不是 Encode。
2021-04-08 11:42:24
+1 我使用了 Html.Raw,但从未找到 Json.Encode,只是使用 JavaScriptSerializer 将控制器中的字符串添加到视图模型中
2021-04-12 11:42:24

干得好,您才刚刚开始使用 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 非常垃圾。

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

还要更新,关于您的 JavaScript,最好将上面所有的小部件 JS 包装起来,如下所示:

(
    // all js here
)();

这样,如果您在一个页面上放置多个小部件,就不会发生冲突(除非您需要从页面的其他地方访问这些方法,但在这种情况下,无论如何您都应该向某个小部件框架注册小部件)。现在可能不是问题,但是现在添加括号是一种很好的做法,以便在将来成为需求时节省自己的大量精力,封装功能也是一种很好的 OO 做法。

我收回我之前的陈述“没有任何问题”。一切都有问题。
2021-03-19 11:42:24
@Update 我正在考虑使用该小部件的 .net 静态计数器来生成唯一的对象名称。但是你写的看起来像它会完成同样的事情并且做得更光滑。此外,我确实研究了将小部件“new_widget_event”的创建绑定到页面级对象以跟踪它们,但这样做的最初原因变成了 OBE。所以我可能会在稍后重新访问。感谢我将要发布的所有帮助您建议的修改版本,但解释了为什么我更喜欢它。
2021-03-20 11:42:24
没有任何事情错了它,它只是不能自定义,如果你想要的任何自定义值格式化你手之前做到这一点,基本上让一切字符串:(这是日期最突出的。我知道有简便的解决方法,但他们不应该是必要的!
2021-03-23 11:42:24
为什么说我们不能从控制器返回JSON。这就是它应该如何完成的。使用JavaScriptSerializerReturn Json(object)两者都使用相同的序列化程序。只要您定义了正确的模型,同样将相同的 JSON 发布回控制器将为您重建对象。也许在 MVC2 期间它是一个主要缺点......但今天它轻而易举,非常方便。您应该更新您的答案以反映这一点。
2021-03-26 11:42:24
这看起来很有趣。我打算将数据复制为 json 并将其作为 viewData 传递,但这样看起来更有趣。我会玩这个,让你知道。顺便说一句,这是我第一次在 stackoverflow 上发布问题,花了 5 分钟才得到好的答复,太棒了!!
2021-04-08 11:42:24

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

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

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

在我看来,这很好很干净,并包含在一个可重复使用的助手中。干杯,J
2021-03-19 11:42:24

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

您的操作将是这样的:

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

编辑

刚刚看到你假设这是Model一个视图,所以上面的不是严格正确的,你必须Ajax调用控制器方法来获取它,ascx然后本身就没有模型,我会留下我的代码以防万一它对您有用,您可以修改电话

编辑 2 只是将 id 放入代码中

谢谢,我最初是使用 jQuery get json 调用来做这个的,并计划让 HTML 元素从 json 中填充它们自己。然而,我们现在遵循的模式是我们的视图应该返回一个模型视图,这是填充基本 HTML 元素(如表格等)的最简单方法。我可以以 JSON 格式发送与 ViewData 相同的数据,但这似乎很浪费。
2021-03-16 11:42:24
但他无法将其渲染到视图中,他必须进行第二次 ajax 调用
2021-03-21 11:42:24
您不应该将 JSON 嵌入到查看结果中。OP 要么需要坚持实践的标准 MVC 并返回模型或视图模型,要么执行 AJAX。绝对没有理由在视图中嵌入 JSON。那只是非常脏的代码。这个答案是正确的方法,也是微软实践推荐的方法。投票是不必要的,这绝对是正确的答案。我们不应该鼓励糟糕的编码实践。通过 AJAX 的 JSON 或通过视图的模型。没有人喜欢带有混合标记的意大利面条式代码!
2021-03-31 11:42:24
这个解决方案会导致以下问题:stackoverflow.com/questions/10543953/...
2021-04-13 11:42:24

@Html.Raw(Json.Encode(object)) 可用于将 View Modal 对象转换为 JSON