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>
}

控制器

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

        public JsonResult GetJson(Person person) {            

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

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

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

  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 序列化程序。

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

4

1 回答 1

14

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

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

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; }
}

您可以想象任何您喜欢的复杂层次结构(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脚本包含到您的页面中。

于 2012-04-02T14:36:03.273 回答