Posted in Javascript onMay 07, 2010
调用jQuery的ajax方法时,jQuery会根据post或者get协议对参数data进行序列化;
如果提交的数据使用复杂的json数据,例如:
{userId:32323,userName:{firstName:"李",lastName:"李大嘴"}}
那么服务器是无法正常接收到完整的参数,因为jQuery对data的序列化,是使用了键值对拼装的方式;
参数拼装成 userId=32323&userName=object ; userName所指向的对象被序列化成字符串"object"
如何才能把一个复杂的object对象提交到后台的action参数中呢?
首先,解决jQuery对于参数序列化的问题:
/*对象序列化为字符串*/ String.toSerialize = function(obj) { var ransferCharForJavascript = function(s) { var newStr = s.replace( /[\x26\x27\x3C\x3E\x0D\x0A\x22\x2C\x5C\x00]/g, function(c) { ascii = c.charCodeAt(0) return '\\u00' + (ascii < 16 ? '0' + ascii.toString(16) : ascii.toString(16)) } ); return newStr; } if (obj == null) { return null } else if (obj.constructor == Array) { var builder = []; builder.push("["); for (var index in obj) { if (typeof obj[index] == "function") continue; if (index > 0) builder.push(","); builder.push(String.toSerialize(obj[index])); } builder.push("]"); return builder.join(""); } else if (obj.constructor == Object) { var builder = []; builder.push("{"); var index = 0; for (var key in obj) { if (typeof obj[key] == "function") continue; if (index > 0) builder.push(","); builder.push(String.format("\"{0}\":{1}", key, String.toSerialize(obj[key]))); index++; } builder.push("}"); return builder.join(""); } else if (obj.constructor == Boolean) { return obj.toString(); } else if (obj.constructor == Number) { return obj.toString(); } else if (obj.constructor == String) { return String.format('"{0}"', ransferCharForJavascript(obj)); } else if (obj.constructor == Date) { return String.format('{"__DataType":"Date","__thisue":{0}}', obj.getTime() - (new Date(1970, 0, 1, 0, 0, 0)).getTime()); } else if (this.toString != undefined) { return String.toSerialize(obj); } }
jQuery异步请求:
$(function() { /*按钮点击事件*/ $("#btn_post_test").click(function() { var data = [ { UserId: "11", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming", "xiaohong"] }, { UserId: "22", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming", "xiaohong"] }, { UserId: "33", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming", "xiaohong"] } ]; $.post("Home/Test", { users: String.toSerialize(data) }, function(text) { alert(String.toSerialize(text)); }, "json"); }); });
点击按钮提交数据,监控浏览器,可以发现提交的数据是json对象的序列化后的内容:
POST /Home/Test HTTP/1.1 x-requested-with: XMLHttpRequest Accept-Language: zh-cn Referer: http://localhost:3149/test.html Accept: application/json, text/javascript, */* Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E) Host: localhost:3149 Content-Length: 501 Connection: Keep-Alive Cache-Control: no-cache Cookie: CookieGlobalLoginUserID=16063 users=%5B%7B%22UserId%22%3A%2211%22%2C%22Name%22%3A%7B%22FirstName%22%3A%22323%22%2C%22LastName%22%3A%222323%22%7D%2C%22Keys%22%3A%5B%22xiaoming%22%2C%22xiaohong%22%5D%7D%2C%7B%22UserId%22%3A%2222%22%2C%22Name%22%3A%7B%22FirstName%22%3A%22323%22%2C%22LastName%22%3A%222323%22%7D%2C%22Keys%22%3A%5B%22xiaoming%22%2C%22xiaohong%22%5D%7D%2C%7B%22UserId%22%3A%2233%22%2C%22Name%22%3A%7B%22FirstName%22%3A%22323%22%2C%22LastName%22%3A%222323%22%7D%2C%22Keys%22%3A%5B%22xiaoming%22%2C%22xiaohong%22%5D%7D%5D
其次,后台服务器处理参数绑定:
using System.Collections.Generic; using System.Web.Mvc; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace WebOS.Controllers { [HandleError] public class HomeController : Controller { /// <summary> /// 测试方法 /// </summary> /// <param name="users">用户数据</param> /// <returns>提交的用户数组</returns> public ActionResult Test([ModelBinder(typeof(JsonBinder<User>))]List<User> users) { return Json(users, JsonRequestBehavior.AllowGet); } } /// <summary> /// 对象实体 /// </summary> [JsonObject] public class User { [JsonProperty("UserName")] public UserName Name { get; set; } [JsonProperty("UserId")] public string UserId { get; set; } [JsonProperty("Keys")] public List<string> Keys { get; set; } } /// <summary> /// 对象实体 /// </summary> [JsonObject] public class UserName { [JsonProperty("FirstName")] public string FirstName { get; set; } [JsonProperty("LastName")] public string LastName { get; set; } } /// <summary> /// Json数据绑定类 /// </summary> /// <typeparam name="T"></typeparam> public class JsonBinder<T> : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { //从请求中获取提交的参数数据 var json = controllerContext.HttpContext.Request.Form[bindingContext.ModelName] as string; //提交参数是对象 if (json.StartsWith("{") && json.EndsWith("}")) { JObject jsonBody = JObject.Parse(json); JsonSerializer js = new JsonSerializer(); object obj = js.Deserialize(jsonBody.CreateReader(), typeof(T)); return obj; } //提交参数是数组 if (json.StartsWith("[") && json.EndsWith("]")) { IList<T> list = new List<T>(); JArray jsonRsp = JArray.Parse(json); if (jsonRsp != null) { for (int i = 0; i < jsonRsp.Count; i++) { JsonSerializer js = new JsonSerializer(); object obj = js.Deserialize(jsonRsp[i].CreateReader(), typeof(T)); list.Add((T)obj); } } return list; } return null; } } }
前端获取到后台返回的数据,结果就是用户提交的数据:
后台json反序列化使用了Newtonsoft.Json 组件,有关资料请参考:http://james.newtonking.com/
使用jQuery向asp.net Mvc传递复杂json数据-ModelBinder篇
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@