asp.net-mvc-4 - 将复杂的 View 模型 POST 到 Controller

标签 asp.net-mvc-4 knockout.js knockout-mapping-plugin

我试图掌握背后的概念 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/

相关文章:

knockout.js - 在使用ko.mapping插件生成的observableArray中插入计算出的可观察到的 knockout

asp.net-mvc - 如何将值从提交按钮动态传递给 mvc?

c# - mvc 4 - Jquery mobile - @section 脚本在导航后不起作用

knockout.js - 无法处理绑定(bind)

javascript - Knockout.js 跟踪选中的复选框

javascript - knockout . foreach 一个 child 的 child 不工作

c# - 如何在ASP.NET MVC编辑页面中为HttpPostedFileBase创建输入类型文件?

c# - SimpleMembership Provider 不分配 ID

javascript - 如果数据绑定(bind)对象只有名称,那么 knockout 如何知道它?

javascript - knockout 简单绑定(bind)问题