Asp.net mvc 4 将复杂的viewmodel发布到控制器
我正在努力掌握淘汰赛(2.2.0)背后的概念Asp.net mvc 4 将复杂的viewmodel发布到控制器,asp.net-mvc-4,knockout.js,knockout-mapping-plugin,Asp.net Mvc 4,Knockout.js,Knockout Mapping Plugin,我正在努力掌握淘汰赛(2.2.0)背后的概念 由于我使用的是ASP.NET MVC 4,我想我可以遵循一个具有“复杂”视图模型(主详细信息)的示例 我唯一能找到的就是 代码很容易阅读,我已经知道如何从服务器读取视图模型并在客户机上构建视图模型 这是我的C#视图模型: public class Person { public Person() { this.Phones = new List<Phone>(); } public stri
由于我使用的是ASP.NET MVC 4,我想我可以遵循一个具有“复杂”视图模型(主详细信息)的示例 我唯一能找到的就是 代码很容易阅读,我已经知道如何从服务器读取视图模型并在客户机上构建视图模型 这是我的C#视图模型:
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; }
}
我使用了Rob Conry使用的相同模式,上面的代码是一个简化版本
我的看法是:
@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" />
}
并发送到控制器:
$.post("/orders/edit", data, callback);
[HttpPost]
public JsonResult Index(Models.Person viewModel)
{
...
}
var model = ko.mapping.fromJS(data);
//...
$.ajax({
type: 'POST',
url: "/orders/edit",
contentType: "application/json",
data: ko.mapping.toJSON(model),
success: callback
});
我似乎无法使此代码与我的视图模型一起工作。
我的控制器:
$.post("/orders/edit", data, callback);
[HttpPost]
public JsonResult Index(Models.Person viewModel)
{
...
}
var model = ko.mapping.fromJS(data);
//...
$.ajax({
type: 'POST',
url: "/orders/edit",
contentType: "application/json",
data: ko.mapping.toJSON(model),
success: callback
});
似乎无法反序列化子级,如果调试客户端,我可以看到seralize
方法也无法序列化它们
实际上,我不明白他为什么要把表单序列化。因为我们有一个由knockout管理的视图模型。
难道没有其他方法可以序列化像这样的“复杂”模型并将其发布到控制器吗
您认为解决方案(MvcMusicStore)是正确地完成任务,还是应该遵循其他模式
任何帮助都将不胜感激
更新
我想我已经找到了解决方案,但我还需要做更多的测试。如果我使用toJSONKO方法:
var data = ko.toJSON(model);
我可以正确序列化整个viewmodel;然后我必须使用$.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为我提供了有用的信息,我还整理了一个简单的,以防其他人感兴趣。问题是,在表中,您的
输入
元素没有名称
属性
您可以使用设置名称,因为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>
注意,在这种情况下,您不能使用$.post
,因为您需要将contentType
指定为“application/json”
但我认为没有推荐的方法来做到这一点。$(“#orderForm”).serialize()
(使用我提到的正确输入名称)和ko.toJSON(model)
都可以工作,因为它们的区别仅仅在于为ajax请求准备/编码数据的方式
我认为这更像是个人的偏好。在这种特殊情况下,使用
ko.toJSON(model)
方式似乎更好,因为您不必为ASP.NET MVC生成特殊的输入名称。您可以将viewmodel原样发送到服务器。使用击倒时感觉更自然。我会选择nemesv第二个选项的变体。发布序列化的viewmodel,而不是尝试使用jQuery序列化表单
由于您的数据类型很复杂,并且Asp.net MVC在将其转换为viewmodel时遇到问题,因此您还需要使用上介绍的$.toDictionary()
插件
实际上,您可以使用
$.post
<代码>$.post(url、数据、fn、“json”)@MichaelBerkompas no第四个参数是数据类型
:期望从服务器获得的数据类型。但对于ASP.NET MVC,您需要设置contentType
,这是发送给sensver的数据类型。
Hmm。。。我从来没有对我们的MVC应用程序进行过$post调用。但是,如果您希望返回JSON,则需要指定JSON的响应类型。感谢您的回复。我更新了我的问题,因为在此期间,我找到了一个与你类似的解决方案。@nemesv你真聪明。感谢您抽出时间提供此答案。我很难做到这一点(复杂类型列表),因为我使用了$.post方法而不是$.ajax,也使用了ko.toJS方法而不是ko.mapping.toJSON。非常感谢!谢谢你的回复,迈克尔。我更新了我的问题,因为我想我已经找到了解决办法。我似乎不能使用toJS,我读过你链接的文章,但它似乎过时了。我希望找到一个更好的解决方案,也许,一些文章或样本。感谢应用程序!这正是我需要的!