MVC 3 - JSON序列化程序

Mic*_*ync 4 asp.net jquery json jsonserializer asp.net-mvc-3

我有以下模型,视图和控制器.

模型

 public class Person {
        public string Name;// { get; set; }
        public string Occupation { get; set; }
        public int Salary { get; set; }
        public int[] NumArr { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

视图

<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>
}
Run Code Online (Sandbox Code Playgroud)

调节器

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

        public JsonResult GetJson(Person person) {            

            return Json(......);
        }
    }
Run Code Online (Sandbox Code Playgroud)

基于上面的代码,我想问三个问题.

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

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

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

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

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

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

Dar*_*rov 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序列化参数的方式时.这种变化恰好与模型绑定器在绑定到列表时在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; }
}
Run Code Online (Sandbox Code Playgroud)

您可以想象您喜欢的任何复杂层次结构(除了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) {

    }
});
Run Code Online (Sandbox Code Playgroud)

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