MVC 3 - JSON序列化程序

时间:2012-04-02 14:28:13

标签: asp.net json asp.net-mvc-3 jquery jsonserializer

我有以下型号,视图和控制器。

模型

 public class Person {
        public string Name;// { get; set; }
        public string Occupation { get; set; }
        public int Salary { get; set; }
        public int[] NumArr { get; set; }
    }

查看

<input type="button" id="Test" value="Test" />

@section Javascript{
<script type="text/javascript">
    $(function () {
        $("#Test").click(function () {
            var data = { Name: "Michael Tom", Occupation: "Programmer", Salary: 8500, NumArr: [2,6,4,9] };
            var url = "Home/GetJson";
            $.ajax({
                url: url,                
                dataType: "json",
                type: "POST",
                data: data,
                traditional: true,
                success: function (result) {

                }
            });

        });
    });        
</script>
}

控制器

public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public JsonResult GetJson(Person person) {            

            return Json(......);
        }
    }

根据上述代码,我想问三个问题。

  1. 如果我们使用公共字段而不是属性,则序列化程序不会将json对象序列化为C#模型,因此对于控制器中的“名称”字段,我总是得到null。为什么会这样?

  2. 如果我将NumArr属性的类型更改为List,则它不起作用。我们如何使用List而不是int []?我知道我从JS传递数组。我们也可以从JS传递List吗?

  3. 我在View的Javascript代码块中使用“traditional:true”,因为序列化不适用于“traditional:false”。我听说jQuery有三个版本的Json序列化程序。 ASP.NET MVC的序列化程序仅支持旧版本。这是真的吗?

  4. 3.1。如果这是真的,我想知道你何时会得到支持jQuery最新版本的MVC序列化器的最新版本。

    3.2。有没有办法注册自定义Javascript Serializer就像我们可以注册自定义视图引擎?我的朋友建议我可以注册自定义值提供程序或自定义模型绑定器,并在我的自定义值提供程序/模型绑定器中使用自定义JS序列化程序。

    提前致谢。如果您不清楚我的问题,请随时告诉我。谢谢!

1 个答案:

答案 0 :(得分:14)

  

1)如果我们使用公共字段而不是属性,序列化程序不会将json对象序列化为C#模型,所以我总是得到null   控制器中的“名称”字段。为什么会这样?

因为模型绑定器仅适用于属性。这是设计的。通常,字段在您的类中应该是私有的。它们是实现细节。使用属性将一些行为暴露给外部世界。

  

2)如果我将NumArr属性的类型更改为List,则它不会   工作。我们如何使用List而不是int []?我知道我正在通过   来自JS的数组。我们也可以从JS传递List吗?

它应该工作。无论您使用的是List<int>IEnumerable<int>还是int[],它都是相同的并且有效。如果你想使用一些复杂对象的集合,例如List<SomeComplexType>,那么什么是行不通的(请参阅下面的答案以获得解决方案)。

  

3)我在View的Javascript代码块中使用“traditional:true”因为   序列化不适用于“traditional:false”。我听说   jQuery有三个版本的Json序列化程序。 ASP.NET MVC的序列化程序   仅支持旧版本。这是真的吗?

是的,当jQuery 1.4改变了jQuery序列化参数的方式时,traditional parameter被引入了jQuery 1.4。这种变化恰好与模型绑定器在binding to lists时在MVC中使用的标准约定不兼容。

因此,下载一个javascript调试工具,如FireBug并开始播放。您将在设置此参数时看到jQuery发送请求的方式不同。


所有这些都说我会建议您将JSON编码的请求发送到您的控制器操作。这将适用于任何复杂的对象,您不必问自己使用的是哪个版本的jQuery,或者因为JSON是标准的可互操作格式。标准互操作格式的优点在于,无论您使用哪种系统,您都应该能够使它们使用相同的语言(除非这些系统中存在错误,并且它们不遵守定义的标准)。

但是现在你可以告诉我application/x-www-form-urlencoded也是一种标准且不可操作的格式。这是真的。问题是模型绑定器在将输入字段的名称绑定到模型的属性时使用约定。而这个惯例远非可互操作或行业标准。

例如,您可以拥有模型层次结构:

public class Person
{
    public string Name { get; set; }
    public string Occupation { get; set; }
    public int Salary { get; set; }
    public List<SubObject> SubObjects { get; set; }
}

public class SubObject
{
    public int Id { get; set; }
    public string Name { get; set; }
}

您可以想象您喜欢的任何复杂层次结构(除了JSON格式不支持的循环引用之外)。

然后:

var data = { 
    name: "Michael Tom", 
    occupation: "Programmer", 
    salary: 8500, 
    subObjects: [
        { id: 1, name: 'sub 1' },
        { id: 2, name: 'sub 2' },
        { id: 3, name: 'sub 3' }
    ] 
};

$.ajax({
    url: "Home/GetJson",
    type: "POST",
    data: JSON.stringify({ person: data }),
    contentType: 'application/json',
    success: function (result) {

    }
});

我们将Content-Type请求HTTP标头设置为application/json以指示请求是JSON编码的内置JSON值提供程序工厂(使用JSON.stringify方法)并将其解析回来到您的强类型模型。 JSON.stringify方法本身内置于现代浏览器中,但如果您想支持旧版浏览器,则可以在页面中加入json2.js脚本。