从 chrome 中截图可以看到如下:
传递的数据是一串 Form 数据,根据命名匹配的原则,也是可以取得数据的。
将 option 的代码改成如下
- var option = {
- url: '/test/ReadPerson',
- type: 'POST',
- data: JSON.stringify(person),
- dataType: 'html',
- success: function (result) { alert(result); }
- };
- $.ajax(option);
其中 JSON.stringify 方法签名为 stringify (value [ , replacer [ , space] ] ),根据 ECMA-262 标准 stringify 函数返回的是 JSON 格式的字符串。它可以有 3 个参数。摘抄如下: The stringify function returns a String in JSON format representing an ECMAScript value. It can take three parameters. The first parameter is required. The value parameter is an ECMAScript value, which is usually an object or array, although it can also be a String, Boolean, Number or null. The optional replacer parameter is either a function that alters the way objects and arrays are stringified, or an array of Strings and Numbers that acts as a white list for selecting the object properties that will be stringified. The optional space parameter is a String or Number that allows the result to have white space injected into it to improve human readability. 默认的 ContentType 的属性值是 "application/x-www-form-urlencoded" 引自 http://www.w3.org/TR/html401/interact/forms.html#adef-enctype 看请求头的截图:
因此,传递到 controller 的是一个 json 字符串,MVC 根据命名匹配也是可以获得到参数的值。
将将 option 的代码改成如下
- var option = {
- url: '/test/ReadPerson',
- type: 'POST',
- data: person,
- dataType: 'html',
- contentType: 'application/json',
- success: function (result) { alert(result); }
- };
把 contentType 改成 json 格式,那么得到的是出错的信息。虽然 person 是 json 对象,但是 jquery 中的 ajax,data 会自动的被转换成查询字符串格式 key1=value1&key2=value2 这种形式,很显然这种形式不是 json 格式,因此会出错。要避免转换成查询字符串格式,只需要设置 processData 为 fasle 即可。processData 默认是 true。这里需要注意的是:当指定了 contentType 的时候,数据将不再按照 Form Data 的形式提交了,而是变成 Request Data 的形式提交。可以从图上的 Request Header 中看出。需要注意的是,Form Data 提交的数据可以由 FormCollection 获得到。Request Data 方式提交的则不能通过 FormCollection 获得。如果把 processData 设置为默认值 true。
如果把 processData 设置为 false。
以上两种方式,按照 application/json 的类型传给都会失败,因为 json 是基于文本的格式,上面两种方式传递的都不是 json 文本。因此会出错。
因此,把 option 改成:
- var option = {
- url: '/test/ReadPerson',
- type: 'POST',
- data:JSON.stringify(person),
- dataType: 'html',
- contentType: 'application/json',
- success: function (result) { alert(result); }
- };
则传递的就是 json 文本,因此根据命名匹配,就能获得值了。
对于较为简单是数据类型,有时候不指定 contentType 也能通过命名匹配传值。但是对于稍微复杂点的数据类型,有时指定 contentType: 'application/json', 处理起来更加方便。如果一个 controller 里的 action 方法是接受一个 List 类型的参数,比如:public ActionResult ReadPersons(List
- var persons = [{
- id: "001",
- name: "zhangsan",
- age: "20",
- gender: true,
- city: "shanghai"
- },
- {
- id: "002",
- name: "lisi",
- age: "21",
- gender: false,
- city: "beijing"
- }
- ];
单纯一个数组传递是作为 data 传递是,Form Data 也是无法识别出的。因此把这个数组再次组成一个 json 形式。如下:其中 json 的键值用 model 是为了能和 controller 中的参数名相同,可以匹配。
- var jsonp = {
- model: persons
- };
- var option = { url: '/test/ReadPersons',
- type: 'POST',
- data: jsonp,
- dataType: 'html',
- success: function(result) {
- alert(result);
- }
- };
由于未指定 contentType,因此是默认的 application/x-www-form-urlencoded。此时是按照 Form Data 的方式传递的,
可以从截图中看到。但是这种格式的数据,controller 中只能获得指定 model 用 2 个元素,无法获得元素中属性的值。
如果把 data 改成 JSON.stringify(jsonp),如下:
- var option = {
- url: '/test/ReadPersons',
- type: 'POST',
- data: JSON.stringify(jsonp),
- dataType: 'html',
- success: function (result) { alert(result); }
- };
那么传递过去的 Form Data 是一串字符串,controller 跟无法识别出这个东西,因此获不到值。如果仅仅设置 contentType: 'application/json', 而传递的又不是 json 格式的数据,如下:
那么传递过去的 Form Data 是一串字符串,controller 跟无法识别出这个东西,因此获不到值。如果仅仅设置 contentType: 'application/json', 而传递的又不是 json 格式的数据,如下:
- var option = {
- url: '/test/ReadPersons',
- type: 'POST',
- data: jsonp,
- dataType: 'html',
- contentType: 'application/json',
- success: function (result) { alert(result); }
- };
因为 jquery 的 ajax 方法会把 data 转换成查询字符串,因此就变成如下的样子。这串文本当然不符合 json 格式,因此会出现下面的错误。
如果设置 contentType: 'application/json', 并且设置 data: JSON.stringify(persons),如下:
- var option = {
- url: '/test/ReadPersons',
- type: 'POST',
- data: JSON.stringify(persons),
- dataType: 'html',
- contentType: 'application/json',
- success: function (result) { alert(result); }
- };
那么可以获得到真正完整的 json 数据了
最后,此处再演示一个更复杂的参数类型,以便加深理解。首先看一下 Controller 中的方法签名,TestClassB 和一个 TestClassA 的 List。稍显复杂。
- public ActionResult Fortest(TestClassB TB,List<TestClassA> TA)
- {
- string result = "";
- return Content(result);
- }
再看 TestClassA 和 TestClassB,更显复杂。但是结构要清晰的话,也不是很难。
- public class TestClassA { public string a1 {
- set;
- get;
- } public List < string > a2 {
- set;
- get;
- }
- } public class TestClassB { public string b1 {
- set;
- get;
- } public InnerTestClassC ITCC {
- set;
- get;
- } public class InnerTestClassC { public List < int > c1 {
- set;
- get;
- }
- }
- }
看 js 代码:逐步的构造出一个 json 格式。
- $("#btn").click(function () {
- var jsondata = { TB: {}, TA: [] };
- jsondata.TB.b1 = "b1";
- jsondata.TB.ITCC = {};
- jsondata.TB.ITCC.c1 = new Array(1, 2, 3, 4);
- var ta1 = {};
- ta1.a1 = "a1";
- ta1.a2 = new Array("a", "b", "x", "y");
- var ta2 = {};
- ta2.a1 = "a2";
- ta2.a2 = new Array("a2", "b2", "x2");
- jsondata.TA.push(ta1);
- jsondata.TA.push(ta2);
- var option = {
- url: '/test/Fortest',
- type: 'POST',
- data: JSON.stringify(jsondata),
- dataType: 'html',
- contentType: 'application/json',
- success: function (result) { alert(result); }
- };
- $.ajax(option);
- });
最终,发送出去的 json 字符串如下:{"TB":{"b1":"b1","ITCC":{"c1":[1,2,3,4]}},"TA":[{"a1":"a1","a2":["a","b","x","y"]},{"a1":"a2","a2":["a2","b2","x2"]}]}Controller 接收到这个 json 串后,就能自动的匹配参数了。具体得到的参数如下截图:
总结:1. 不指定 contentType 的话,默认都是 application/x-www-form-urlencoded 方式发送。此时即便发送的是 json 格式的数据,默认情况下,jquery 的 ajax 也会把他转为查询字符串的形式(可以通过修改 ajax 参数修改),以 FormData 的形式发送出去。2. 不指定 contentType 的时候,如果 controller 中的方法签名比较简单,那么即便是 FormData 形式的数据也能由 MVC 的命名匹配规则获取到数据。3. 指定 contentType 为'application/json'时候,发送的数据必须是符合 json 规范的字符串。通常,使用 JSON.stringify(jsondata) 有较好的可读性,可以获得一个 json 字符串。当然,不是必须的。使用拼接的字符串,只要是符合 json 规范的,也是可以发送的。4. 如果 contentType 为'application/json'时,发送的 data 不是符合 json 规范的字符串,则会出错。5. 通常情况下,尽量指定 contentType 为'application/json',并且发送 json 字符串作为发送数据,这样可读性更好,并且对于复杂的函数签名,也能起到很好的匹配。
来源: http://www.phperz.com/article/17/0415/276003.html