从未调用过服务器操作 - JSON反序列化失败?

时间:2010-12-20 19:13:14

标签: c# jquery asp.net-mvc json

我的控制器中有简单的操作:

[HttpPost]
public JsonResult Action(MenuSet menuSet)
{
   //...
}

其中MenuSet是:

public class MenuSet
{      
    private IEnumerable<MenuEntry> _menuEntries;

    public IEnumerable<MenuEntry> MenuEntries
    {
        get { return _menuEntries; }
        set { _menuEntries = value; }
    }
}

public class MenuEntry
{
    private string _parentPageName;
    private IEnumerable<string> _orderedPages;

    public string ParentPageName
    {
        get { return _parentPageName; }
        set { _parentPageName = value; }
    }
    public IEnumerable<string> OrderedPages
    {
        get { return _orderedPages; }
        set { _orderedPages = value; }
    }
}

从客户端,我正在以下面的方式调用此操作:

$.post("Controller/Action", 
       $.param({ MenuEntries: prepareData() }, true), 
       null, 
       "json");

其中prepareData()函数返回MenuEntries集合:

function prepareData() {
    var menuEntries = new Array();
    var menuEntry = {
        ParentPageName: null,
        OrderedPages: getPagesOrder()
    }
    menuEntries.push(menuEntry);
    return menuEntries;
}

function getPagesOrder() {
    var values = new Array();
    values.push('samplePageName')
    return values;
}

但是JSON对象似乎没有反序列化到服务器端的模型 - 永远不会调用控制器操作。如何使这项工作?

3 个答案:

答案 0 :(得分:1)

亚雷克,

如果使用$ ajax而不是$ post,它可以正常工作。我在index.aspx页面上添加了一个按钮,如下所示:

<input type="button" id="btnGo" value="Go" />

另外,添加一个新的javascript文件并将以下内容粘贴到其中(将其保存为/scripts/toJson.js):

//Source: http://www.overset.com/2008/04/11/mark-gibsons-json-jquery-updated/
(function($) {
  m = {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '"': '\\"',
    '\\': '\\\\'
},
$.toJSON = function(value, whitelist) {
    var a,          // The array holding the partial texts.
        i,          // The loop counter.
        k,          // The member key.
        l,          // Length.
        r = /["\\\x00-\x1f\x7f-\x9f]/g,
        v;          // The member value.

    switch (typeof value) {
        case 'string':
            return r.test(value) ?
            '"' + value.replace(r, function(a) {
                var c = m[a];
                if (c) {
                    return c;
                }
                c = a.charCodeAt();
                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
            }) + '"' :
            '"' + value + '"';

        case 'number':
            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':
            return String(value);

        case 'object':
            if (!value) {
                return 'null';
            }
            if (typeof value.toJSON === 'function') {
                return $.toJSON(value.toJSON());
            }
            a = [];
            if (typeof value.length === 'number' &&
                !(value.propertyIsEnumerable('length'))) {
                l = value.length;
                for (i = 0; i < l; i += 1) {
                    a.push($.toJSON(value[i], whitelist) || 'null');
                }
                return '[' + a.join(',') + ']';
            }
            if (whitelist) {
                l = whitelist.length;
                for (i = 0; i < l; i += 1) {
                    k = whitelist[i];
                    if (typeof k === 'string') {
                        v = $.toJSON(value[k], whitelist);
                        if (v) {
                            a.push($.toJSON(k) + ':' + v);
                        }
                    }
                }
            } else {
                for (k in value) {
                    if (typeof k === 'string') {
                        v = $.toJSON(value[k], whitelist);
                        if (v) {
                            a.push($.toJSON(k) + ':' + v);
                        }
                    }
                }
            }
            return '{' + a.join(',') + '}';
    }
};

})(jQuery);

在index.aspx中引用此新文件

<script src= "/scripts/toJson.js" type="text/javascript"></script>

并将$ post javascript替换为:

$(document).ready(function() {
    $('#btnGo').click(function() {
        $.ajax({
            type: "POST",
            url: '<%=Url.Content("~/Home/Action") %>',
            dataType: "json",
            data: { MenuEntries: prepareData() },
            success: function(msg) {
                alert(msg);
            },
            error: function(xhr) { alert(xhr.statusText); }
        });

    });
});

function prepareData() {
    var menuEntries = new Array();
    var menuEntry = {
        ParentPageName: "myPageName",
        OrderedPages: getPagesOrder()
    }
    menuEntries.push(menuEntry);
    // this serialises the javascript array correctly
    return $.toJSON(menuEntries);
}

尝试将操作更改为下面的代码并尝试使用它(这为您提供了两个选项来检查发布的数据):

[HttpPost]
public JsonResult Action(FormCollection formCollection)
{
    NameValueCollection test = HttpContext.Request.Form;
    // return Json(test[0]);
    return Json(formCollection[0]);
}

它在控制器中的“Action”操作中正确反序列化。

试一试。我确定它是“固定的”

[edit] - 修复了一半......你需要研究如何玩这个对象。即通过formCollection或通过测试varibale。两者都以不同的形式给对象。!!

答案 1 :(得分:0)

第一

您也可以在操作方法中使用IList<MenuEntry>作为参数类型。

第二

这两篇博文将帮助您完成 自动模型验证,而其他人的解决方案并非如此。

Asp.net MVC model binding to List<T>
Sending complex JSON objects to Asp.net MVC using jQuery

答案 2 :(得分:0)

您可以使用Phil Haack's解决方案将json传递给控制器​​的操作方法。

希望这有帮助!