MVC 3 - JSON序列化器

4
我有以下的模型、视图和控制器。 模型
 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>
}

Controller

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

        public JsonResult GetJson(Person person) {            

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

基于上述代码,我想问三个问题。
  1. 如果我们使用公共字段而不是属性,则序列化程序不会将JSON对象序列化为C#模型,因此在控制器中始终获取“Name”字段的值为空。为什么会这样?
  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序列化程序,就像我们可以注册自定义视图引擎一样?我的朋友建议我注册自定义值提供程序或自定义模型绑定器,并在我的自定义值提供程序/模型绑定器中使用自定义JS序列化程序。
提前感谢。如果您对我的问题不清楚,请随时让我知道。谢谢!
1个回答

14

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

这是因为模型绑定器只能与属性一起使用。这是设计上的限制。通常情况下,类中的字段应该是私有的。它们是实现细节。使用属性来向外部公开某些行为。

2) 如果我将NumArr属性的类型更改为List,则它无法正常工作。我们如何使用List替换int[]?我知道我正在从JS传递数组。我们也可以从JS传递List吗?

应该可以工作。无论您使用List<int>IEnumerable<int>还是int[],它都是相同的,并且可以正常工作。不起作用的是如果您想要使用某些复杂对象的集合,例如List<SomeComplexType>(请参阅下面的答案以获取解决方案)。

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

是的,traditional参数是在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; }
}

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

    }
});

我们将HTTP请求头的Content-Type设置为application/json,以通知内置的JSON值提供者工厂该请求已经使用JSON.stringify方法进行了JSON编码,并且会将其解析回强类型模型。现代浏览器本身就具备JSON.stringify方法,但如果您想支持旧版浏览器,可以将json2.js脚本包含在您的页面中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接