Lef*_*tyX 5 asp.net-mvc-4 knockout-mapping-plugin knockout.js
我试图掌握Knockout(2.2.0)背后的概念.
由于我正在使用ASP.NET MVC 4,我想我可以遵循一个具有"复杂"视图模型(master-details)的示例.
我唯一能找到的就是MvcMusicStore.
代码很容易阅读,我已经想出如何从服务器读取视图模型并在客户端上构建视图模型.
这是我的C#ViewModel:
public class Person
{
public Person()
{
this.Phones = new List<Phone>();
}
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public IList<Phone> Phones { get; set; }
}
public class Phone
{
public string Model { get; set; }
public string Number { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的控制器将一个填充的模型返回给视图,该视图将其转换为一个挖空视图模型:
var data = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model));
var model = ko.mapping.fromJS(data);
ko.applyBindings(model);
Run Code Online (Sandbox Code Playgroud)
我使用了Rob Conery使用的相同模式,上面的代码是简化版本.
这是我的看法:
@using (@Html.BeginForm("Index", "Home", FormMethod.Post))
{
<input id="Name" name="Name" type="text" data-bind="value: Name" value="" />
<br />
<input id="Surname" name="Surname" type="text" data-bind="value: Surname" value="" />
<br />
<table>
<tbody data-bind="foreach: Phones">
<tr>
<td><input type="text" data-bind='value: Model' /></td>
<td><input type="text" data-bind='value: Number' /></td>
</tr>
</tbody>
</table>
<input type="submit" value="Send" />
}
Run Code Online (Sandbox Code Playgroud)
现在,我想提交我的FORM并在我的控制器上阅读更新的视图模型.
为了达到这个目的,我使用了与MvcMusicStore相同的解决方案.
如果你看第49行, Rob会尝试序列化FORM:
var data = $("#orderForm").serialize();
Run Code Online (Sandbox Code Playgroud)
并POST到控制器:
$.post("/orders/edit", data, callback);
Run Code Online (Sandbox Code Playgroud)
我似乎无法使这个代码与我的视图模型一起工作.我的控制器:
[HttpPost]
public JsonResult Index(Models.Person viewModel)
{
...
}
Run Code Online (Sandbox Code Playgroud)
似乎无法反序列化子进程,如果调试客户端,我可以看到该seralize
方法也无法序列化它们.
实际上,我不明白为什么他会尝试序列化FORM.因为我们有一个由淘汰赛管理的视图模型.有没有其他方法我可以序列化像这样的"复杂"模型并将其发布到控制器?
你认为这个解决方案(MvcMusicStore)是正确的做事还是我应该遵循其他模式?
任何帮助,将不胜感激.
UPDATE
我想我找到了一个解决方案但我必须做更多的测试.
如果我使用toJSON KO方法:
var data = ko.toJSON(model);
Run Code Online (Sandbox Code Playgroud)
我可以将整个viewmodel序列化正确; 然后我必须使用$ .ajax POST数据
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
url: "/Home/Index",
data: dataToSave,
success: callback,
error: function (req, status, error) {
alert("Status: " + status + " Error: " + error);
}
});
Run Code Online (Sandbox Code Playgroud)
这样一切似乎都运行正常,但是,我仍然想知道是否有任何推荐的方法.
解
Michael Berkompas和nemesv给了我有用的信息,我已经整理了一个简单的应用程序,以防其他人感兴趣.
问题是在表格内部,您的input
元素没有name
属性.
您可以使用attr绑定设置名称,因为MVC在模型绑定集合时需要特殊的名称格式,您需要编写:
<tbody data-bind="foreach: Phones">
<tr>
<td><input type="text" data-bind="value: Model, attr: { name: 'Phones[' + $Index() + '].Model' }" /></td>
<td><input type="text" data-bind="value: Number, attr: { name: 'Phones[' + $Index() + '].Number' }" /></td>
</tr>
</tbody>
Run Code Online (Sandbox Code Playgroud)
或者因为你无论如何都拥有你的viewmodel,你可以直接将它发送给你的控制器:
var model = ko.mapping.fromJS(data);
//...
$.ajax({
type: 'POST',
url: "/orders/edit",
contentType: "application/json",
data: ko.mapping.toJSON(model),
success: callback
});
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,您无法使用,$.post
因为您需要指定contentType
为"application/json".
但我认为没有推荐的方法来做到这一点.两者$("#orderForm").serialize()
(具有正确的输入名称,我提到的)和ko.toJSON(model)
工作,因为差异只是如何为ajax请求准备/编码数据.
我认为这更像是个人偏好使用者.在这种特殊情况下,这样做ko.toJSON(model)
似乎更好,因为您不必处理ASP.NET MVC的特殊输入名称的生成.您可以将viewmodel原样发送到服务器.使用淘汰赛时感觉更自然.
归档时间: |
|
查看次数: |
7690 次 |
最近记录: |