使用jQuery向asp.net Mvc传递复杂json数据-ModelBinder篇

  调用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;

  }

  }

  }

  前端获取到后台返回的数据,结果就是用户提交的数据:

使用jQuery向asp.net Mvc传递复杂json数据-ModelBinder篇

  后台json反序列化使用了Newtonsoft.Json 组件,有关资料请参考:http://james.newtonking.com/