我试图掌握背后的概念 knockout (2.2.0) .
因为我正在与 一起工作ASP.NET MVC 4 我想我可以遵循一个具有“复杂” View 模型(主细节)的示例。
我唯一能找到的是 MvcMusicStore .
代码很容易阅读,我已经想出了如何从服务器读取 View 模型并在客户端上构建 View 模型。
这是我的 C# View 模型 :
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; }
}
我的 Controller 向 View 返回一个填充模型,它将其转换为 knockout View 模型:
var data = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model));
var model = ko.mapping.fromJS(data);
ko.applyBindings(model);
我使用了与 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" />
}
现在,我想提交我的 FORM 并在我的 Controller 上阅读更新的 View 模型。
为了实现这一点,我使用了在 MvcMusicStore 中找到的相同解决方案。
如果你看 line 49 Rob 尝试序列化 FORM:
var data = $("#orderForm").serialize();
并POST到 Controller :
$.post("/orders/edit", data, callback);
我似乎无法使此代码与我的 View 模型一起使用。
我的 Controller :
[HttpPost]
public JsonResult Index(Models.Person viewModel)
{
...
}
似乎无法反序列化 child ,如果调试客户端,我可以看到
seralize
方法也不能序列化它们。实际上,我不明白他为什么要对 FORM 进行序列化。因为我们有一个由 knockout 管理的 View 模型。
没有其他方法可以序列化像这样的“复杂”模型并将其发布到 Controller 吗?
您认为该解决方案 ( MvcMusicStore ) 是否正常运行,还是应该遵循其他模式?
任何帮助,将不胜感激。
更新
我想我已经找到了一个解决方案,但我必须做更多的测试。
如果我使用 toJSON KO方法:
var data = ko.toJSON(model);
我可以正确序列化整个 View 模型;然后我必须使用 $.ajax 发布数据
$.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);
}
});
这样一切似乎都可以正常工作,但是,我仍然想知道是否有任何推荐的方法。
解决方案
Michael Berkompas 和 nemesv 给了我有用的信息,我整理了一个简单的 application ,以防万一其他人感兴趣。
最佳答案
问题是在表里面你的input
元素没有 name
属性。
您可以使用 attr binding 设置名称因为当 model binding collection 时 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>
或者,因为您无论如何都有 View 模型,您可以直接将其发送到您的 Controller :
var model = ko.mapping.fromJS(data);
//...
$.ajax({
type: 'POST',
url: "/orders/edit",
contentType: "application/json",
data: ko.mapping.toJSON(model),
success: callback
});
请注意,在这种情况下,您不能使用
$.post
因为您需要指定 contentType
作为“应用程序/json”。但我认为没有推荐的方法来做到这一点。两者
$("#orderForm").serialize()
(使用我提到的正确输入名称)和 ko.toJSON(model)
之所以有效,是因为不同之处仅在于为 ajax 请求准备/编码数据的方式。我认为这更像是个人偏好使用哪个。在这种特殊情况下,执行
ko.toJSON(model)
方法似乎更好,因为您不必处理 ASP.NET MVC 的特殊输入名称的生成。您可以将 View 模型按原样发送到服务器。使用 knockout 时感觉更自然。
关于asp.net-mvc-4 - 将复杂的 View 模型 POST 到 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14144527/