想到在asp.net的mvc中如果使用ajax向服务端传递参数时如果参数是一个类或者是个数组(或List集合)以及更复杂的对象时,服务端总是会发生取不到值的情况,当然网上也有很多解决的例子,但都是在服务端想办法来解决的(比如将json转换为字符串,再在服务端反序列化为一个对象),为何不能在客户端就把这个问题搞定。
其实问题没那么复杂,那是因为在jquery提交Array的数据时,提交的时候始终会在名称后面加上”[]”, 问题就出在这里。另外在服务端对数组和内嵌的js对象进行解析时,需要像这样的格式,比如数组(或List集合)在服务端需要这样{'xxx[0]':'aaa','xxx[1]':'bbb'}的格式,而内嵌对象需要像这样{'xxx.a':'ddd','xxx.b':'hhh'},找到问题的原因就好解决了,如果我们能将json的格式转换为服务端了能够识别的格式,问题岂不迎刃而解。
说干就干,直接上代码
1 //用于MVC参数适配JavaScript闭包函数 2 //2013-7-17 devotion 创建 3 /* 4 使用方式如下: 5 $.ajax({ 6 url: "@Url.Action("AjaxTest")", 7 data: mvcParamMatch(sendData),//在此转换json格式,用于mvc参数提交 8 dataType: "json", 9 type: "post", 10 success:function(result) { 11 alert(result.Message); 12 } 13 }); 14 */ 15 var mvcParamMatch = (function () { 16 var MvcParameterAdaptive = {}; 17 //验证是否为数组 18 MvcParameterAdaptive.isArray = Function.isArray || function (o) { 19 return typeof o === "object" && 20 Object.prototype.toString.call(o) === "[object Array]"; 21 }; 22 23 //将数组转换为对象 24 MvcParameterAdaptive.convertArrayToObject = function (/*数组名*/arrName, /*待转换的数组*/array, /*转换后存放的对象,不用输入*/saveOjb) { 25 var obj = saveOjb || {}; 26 27 function func(name, arr) { 28 for (var i in arr) { 29 if (!MvcParameterAdaptive.isArray(arr[i]) && typeof arr[i] === "object") { 30 for (var j in arr[i]) { 31 if (MvcParameterAdaptive.isArray(arr[i][j])) { 32 func(name + "[" + i + "]." + j, arr[i][j]); 33 } else if (typeof arr[i][j] === "object") { 34 MvcParameterAdaptive.convertObject(name + "[" + i + "]." + j + ".", arr[i][j], obj); 35 } else { 36 obj[name + "[" + i + "]." + j] = arr[i][j]; 37 } 38 } 39 } else { 40 obj[name + "[" + i + "]"] = arr[i]; 41 } 42 } 43 } 44 45 func(arrName, array); 46 47 return obj; 48 }; 49 50 //转换对象 51 MvcParameterAdaptive.convertObject = function (/*对象名*/objName,/*待转换的对象*/turnObj, /*转换后存放的对象,不用输入*/saveOjb) { 52 var obj = saveOjb || {}; 53 54 function func(name, tobj) { 55 for (var i in tobj) { 56 if (MvcParameterAdaptive.isArray(tobj[i])) { 57 MvcParameterAdaptive.convertArrayToObject(i, tobj[i], obj); 58 } else if (typeof tobj[i] === "object") { 59 func(name + i + ".", tobj[i]); 60 } else { 61 obj[name + i] = tobj[i]; 62 } 63 } 64 } 65 66 func(objName, turnObj); 67 return obj; 68 }; 69 70 return function (json, arrName) { 71 arrName = arrName || ""; 72 if (typeof json !== "object") throw new Error("请传入json对象"); 73 if (MvcParameterAdaptive.isArray(json) && !arrName) throw new Error("请指定数组名,对应Action中数组参数名称!"); 74 75 if (MvcParameterAdaptive.isArray(json)) { 76 return MvcParameterAdaptive.convertArrayToObject(arrName, json); 77 } 78 return MvcParameterAdaptive.convertObject("", json); 79 }; 80 })();
使用方法非常简单,看下面的例子:
这是客户端的代码
var sendData = { "Comment": "qqq", "Ajax1": { "Name": "sq", "Age": 55, "Ajax3S": { "Ajax3Num": 234 } }, "Ajax2S": [{ "Note": "aaa", "Num": 12, "Ajax1S": [{ "Name": "sq1", "Age": 22, "Ajax3S": { "Ajax3Num": 456 } }, { "Name": "sq2", "Age": 33, "Ajax3S": { "Ajax3Num": 789 } }] }, { "Note": "bbb", "Num": 34, "Ajax1S": [{ "Name": "sq3", "Age": 44, "Ajax3S": { "Ajax3Num": 654 } }, { "Name": "sq4", "Age": 987 }] }] }; $.ajax({ url: "@Url.Action("AjaxTest")", /* 在此使用闭包函数转换json对象,如果你的json对象自身就是个数组Array, 那么需要指定一个名称,这个名称对应于Action中这个数组参数的名称像这样 data:mvcParamMatch(sendData,"Action中所对应的参数名称") */ data: mvcParamMatch(sendData), dataType: "json", type: "post", success:function(result) { alert(result.Message); }, error:function(a,b,c) { } });
然后是服务端的代码,首先是对应客户端的实体类
1 public class AjaxParamModels 2 { 3 public string Comment { set; get; } 4 5 public Ajax1 Ajax1 { set; get; } 6 7 public List<Ajax2> Ajax2S { set; get; } 8 } 9 10 public class Ajax1 11 { 12 public string Name { set; get; } 13 14 public int Age { set; get; } 15 16 public Ajax3 Ajax3S { set; get; } 17 } 18 19 public class Ajax2 20 { 21 public string Note { set; get; } 22 23 public int Num { set; get; } 24 25 public List<Ajax1> Ajax1S { set; get; } 26 } 27 28 public class Ajax3 29 { 30 public int Ajax3Num { set; get; } 31 }
然后是controller中的action代码
1 public class TestController : Controller 2 { 3 // 4 // GET: /Test/ 5 6 public ActionResult Index() 7 { 8 return View(); 9 } 10 11 public ActionResult AjaxTest(Models.AjaxParamModels model) 12 { 13 //在此可以访问model 14 return Json(new {Message = "qqqqq"}); 15 } 16 }
这样就OK了,不管你这个json对象有多少复杂都没关系,他会自动转换为服务端要求的格式,服务端再也不用操心了。