更新/返回ViewModel返回服务器

时间:2012-10-14 15:05:45

标签: javascript asp.net-mvc asp.net-mvc-4 mvvm breeze

作为web dev和MVC4的新手,我反复遇到同样的设计问题,希望有人能告诉我MVC4世界中正确/支持/等等的解决方案:

基本上,我已经喝了视图模型koolaid,并为我的项目中的每个视图都有视图模型,其中大部分都是动态更新单个页面应用程序的部分子视图。所有收益都很好地生成/呈现视图,然后用户在客户端更新许多值,并且是时候更新服务器了。

举个例子,假设它是一个简单的容器视图模型:

public class Data {
  public List<Prop> Props { get; set; }
}

public class Prop {
  public string Id { get; set; }
  public int Value { get; set; }
}

所以,让我们说用户正在向容器添加新的道具。如何将修改后的对象恢复到服务器?

到目前为止:如果服务器实时同步很重要,我可以在服务器上进行每次添加/更新调用,然后在客户端保持同步,或者让服务器返回更新的视图。对于像这样的简单场景,一切都很好。

但我经常发现自己常常希望客户端能够操作对象(通过view / js / etc),我不需要在服务器上更新,直到完成并提交。我真正想要的是能够通过渲染视图传递对象,通过Javascript与它交互,然后在完成所有操作后将对象传递回控制器。我怎么样? (道歉需要一段时间才能达到目的!)

我见过的替代品:

- 快速&amp; Dirty(Encode viewmodel properties to JavaScript in Razor):肯定会把对象放在客户端的javascript中,虽然看起来好像只是将整个对象序列化到客户端html而没有任何验证等等(尽管我确实认识到了)最终这就是对象如何降低它,但似乎你绕过了整个MVC4对象处理/解析。)

- Upshot.Js似乎很有希望同时获得MS的支持,但似乎已经死了:Current status of Upshot.js

- Breeze.js(http://www.breezejs.com/)似乎是试图接管那里,虽然我担心它是相当新的,并没有广泛采用。

最终让我觉得我错过了一个必然是一个显而易见的替代方案的事情是,所有的部分都已经清楚地构建到MVC4中了。例如,当您使用表单视图时,您的字段将数据绑定到控件,并且在提交表单时,会创建并行JSON对象,将其发送到控制器,然后为您解析为POCO ViewModel对象。这基本上是我正在寻找的往返(虽然保留了完整的JSON对象客户端)。处理这个问题的“正确”方法是什么?

2 个答案:

答案 0 :(得分:2)

Knockout实际上正是我正在寻找的(或另一个客户端MV *框架),我根本就不知道如何使用它。

归功于@Mathletics和其他几个SO解决方案,我们指出了正确的方向,特别是:How to use knockout.js with ASP.NET MVC ViewModels?

关键是使用ko.mapping库,Json在服务器端对模型进行编码或序列化。特别是,这个脚本块在强类型的局部视图中对我很有用:

<script type="text/javascript">
function viewModel() {
    // Additional Knockout Here    
};

var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
var mvcModel = ko.mapping.fromJSON(jsonModel);

var myViewModel = new viewModel();
var g = ko.mapping.fromJS(myViewModel, mvcModel);

ko.applyBindings(g);
</script>

然后你按照正常情况设置使用Knockout:

<div class="row">    
    <div class="span3">
        <h3>Bound Value:</h3>
        <span data-bind="text: PropertyName"></span>
    </div>
</div>

(这需要knockout.js,knockout.mapping.js和Newtonsoft.Json - 尽管Json.Encode同样有效。)

将对象传回去很容易。正常更新您的对象,当您将其传递回控制器时,您已经准备好了Json对象,并将按照正常情况进行解析,以作为服务器端的POCO视图模型传回,完成该轮行程。

答案 1 :(得分:0)

根据您的描述,我可以理解您需要将对象集合传递给控制器​​,然后更新集合。模型绑定到集合将使您更容易。

当绑定到单个字段的集合时,它变得更容易,但是当你想要绑定到对象集合时,它变得有点棘手。有两个选项顺序绑定和非顺序绑定。

顺序绑定:

以下是将发布表单的控制器操作(HTTP POST操作)

public ActionResult UpdateProps(ICollection<Prop> Props) {
    return View(Props);
}

form method="post" action="/Home">    
    <input type="text" name="[0].Id" value="1001" />
    <input type="text" name="[0].Value" value="Prop1" />        

    <input type="text" name="[1].Id" value="" />
    <input type="text" name="[1].Value" value="NewProp" /> 

    <input type="submit" />
</form>

当表单发布时,值将类似于

  

[0] = .ID 1001安培; [0]。价值= PROP1&安培; [1] .ID =安培; [1]。价值= NewProp

您可以看到索引[0]和[1]。模型绑定器将根据索引对对象进行正确分组,您将获得预期的集合。发布后,您的操作将在ICollection Props中获得2个对象。一个是ID 1001,另一个是新添加的。

现在你会注意到,如果你动态添加新的prop,那么你需要使用脚本正确地索引它。或者,如果这对您来说很难,那么您可以使用以上格式发布元素而不是索引元素。您需要解析元素并使用脚本发布表单。数据应按索引排列。解析为您提供了另一个优势,即您只能发布所需的元素,即新添加或修改,而不是全部发布,从而节省了有效负载。

非顺序绑定而不是一系列数字序列中,索引是唯一值,如下所示:

  

[PropId1001] .ID = 1001&安培; [PropId1001]。价值= PROP1&安培; [PropIdTemp233] .ID = “” &安培; [PropIdTemp233]。价值= NewProp