Asp.net mvc 4 将复杂的viewmodel发布到控制器

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

我正在努力掌握淘汰赛(2.2.0)背后的概念
由于我使用的是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,我读过你链接的文章,但它似乎过时了。我希望找到一个更好的解决方案,也许,一些文章或样本。感谢应用程序!这正是我需要的!