2

我有一个用于创建页面的模型:

public class PageCreateModel : ActionModel
{
    public IList<KeyValuePair<Guid, string>> AvailablePermissions { get; set; }
    public IList<KeyValuePair<Guid, string>> AvailableUsers { get; set; }
    public IList<KeyValuePair<Guid, string>> AvailableGroups { get; set; }

    public string Heading { get; set; }
    public bool ShowHeading { get; set; }
    public string Description { get; set; }
    public ICollection<string> RouteUrls { get; set; }
    public IList<KeyValuePair<Guid, string>> SelectedEditingPermissions { get; set; }
    public IList<KeyValuePair<Guid, string>> SelectedEditingUsers { get; set; }
    public IList<KeyValuePair<Guid, string>> SelectedEditingGroups { get; set; }
}

我正在使用淘汰赛映射将其转换为页面加载时的淘汰赛模型:

 var mappedModel = ko.mapping.fromJS(@Html.Raw(JsonConvert.SerializeObject(Model)));

发布和使用此代码后:

mappedModel.save = function(form) {
        mappedModel.AvailablePermissions([]);
        mappedModel.AvailableUsers([]);
        mappedModel.AvailableGroups([]);
        console.log(ko.toJS(mappedModel));
        ko.utils.postJson('@Url.Action("Create", "Page")', { pageCreateModel: ko.toJS(mappedModel) });
    };

它转到此操作:

    [HttpPost]
    public ActionResult Create(PageCreateModel pageCreateModel)
    {

        return View(HydrateModel(pageCreateModel));
    }

此时我的标准属性值已发布查找。但是我的收藏(到目前为止,在我的页面上我只添加了SelectedEditingUsers)在收藏中有空对象。例如,如果在页面上我将 2 个用户添加到集合中,然后我将其发布。MVC 模型的 SelectedEditingUsers 将有一个包含两个的集合,但这些对象包含一个 Empty Guid 和 null 作为值。

这是从 Chrome 控制台发送到服务器的数据:

pageCreateModel:{"AvailablePermissions":[],"AvailableUsers":[],"AvailableGroups":[],"Heading":"Test","ShowHeading":true,"Description":null,"RouteUrls":null,"SelectedEditingPermissions":[],"SelectedEditingUsers":[{"Key":"d81f409a-5fed-4330-8640-004bede4e6fb","Value":"User1"},{"Key":"5628ad64-567b-499d-bee1-cb6c3dc397eb","Value":"User2"}],"SelectedEditingGroups":[],"ActionSuccess":false,"ActionMessage":null,"ko_mapping":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"AvailablePermissions[0].Key":true,"AvailablePermissions[0].Value":true,"AvailablePermissions1.Key":true,"AvailablePermissions1.Value":true,"AvailablePermissions[2].Key":true,"AvailablePermissions[2].Value":true,"AvailablePermissions[3].Key":true,"AvailablePermissions[3].Value":true,"AvailablePermissions[4]...[etc]

How can I fix it so that the full model gets properly received by MVC? I need to use postJSON so I can use RedirectToAction and other similar things.

EDIT: Trying the AJAX call instead:

 mappedModel.save = function(form) {
        mappedModel.AvailablePermissions([]);
        mappedModel.AvailableUsers([]);
        mappedModel.AvailableGroups([]);
        //mappedModel.__ko_mapping__([]);
        //console.log(ko.toJS(mappedModel));
        $.ajax({
            url: '@Url.Action("Create", "Page")',
            type: 'POST',
            data: ko.toJSON(mappedModel),
            contentType: 'application/json; charset=utf-8',
            success: function(data) {
                alert("Success!");
            }
        });
        //ko.utils.postJson('@Url.Action("Create", "Page")', { pageCreateModel: ko.toJS(mappedModel) });
        //ko.utils.postJson($("form")[0], { pageCreateModel: ko.toJS(mappedModel) });
        //ko.utils.postJson('@Url.Action("Test", "Page")', { ko.toJS(mappedModel) });

    };

And I still get the same problem:

enter image description here

And here is the POST from that:

{"AvailablePermissions":[],"AvailableUsers":[],"AvailableGroups":[],"Heading":"Test","ShowHeading":true,"Description":null,"RouteUrls":null,"SelectedEditingPermissions":[],"SelectedEditingUsers":[{"Key":"5628ad64-567b-499d-bee1-cb6c3dc397eb","Value":"User1"},{"Key":"6d7439aa-7728-4add-953f-28b306fff5d0","Value":"User2"}],"SelectedEditingGroups":[],"SelectedViewingPermissions":[],"SelectedViewingUsers":[],"SelectedViewingGroups":[],"ActionSuccess":false,"ActionMessage":null,"ko_mapping":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"AvailablePermissions[0].Key":true,"AvailablePermissions[0].Value":true,"AvailablePermissions1.Key":true,"AvailablePermissions1.Value":true,"AvailablePermissions[2].Key":true,"AvailablePermissions[2].Value":true,"AvailablePermissions[3].Key":true,...etc"

4

1 回答 1

4

ko.utils.postJson doesn't set the Content-Type request header to application/json. It will simply send the request as form encoded value. So use $.ajax instead which allows you to specify the correct content type header:

mappedModel.save = function(form) {
    mappedModel.AvailablePermissions([]);
    mappedModel.AvailableUsers([]);
    mappedModel.AvailableGroups([]);
    $.ajax({
        url: '@Url.Action("Create", "Page")',
        type: 'POST',
        data: ko.toJSON(mappedModel),
        contentType: 'application/json; charset=utf-8',
        success: function(data) {
           ...do something
        }
    });
};

The Content-Type request header is used by ASP.NET MVC when trying to read the request in order to know how is this request being serialized.

In addition to that you might want to replace the IList<KeyValuePair<Guid, string>> types with IList<MyViewModel> where MyViewModel would be a view model class exposing two public properties: Key and Value. I am not sure that the JSON serializer would cope well with those KeyValuePair<Guid, string> type.

于 2013-01-11T22:57:30.167 回答