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



     jQuery提供的ajax方法能很方便的实现客户端与服务器的异步交互,在asp.net mvc 框架使用jQuery能很方便地异步获取提交数据,给用户提供更好的体验!

     调用jQuery的ajax方法时,jQuery会根据post或者get协议对参数data进行序列化;

    如果提交的数据使用复杂的json数据,例如:

    {userId:32323,userName:{firstName:"李",lastName:"李大嘴"}}

    那么服务器是无法正常接收到完整的参数,因为jQuery对data的序列化,是使用了键值对拼装的方式;

    参数拼装成  userId=32323&userName=object ;  userName所指向的对象被序列化成字符串"object"

    如何才能把一个复杂的object对象提交到后台的action参数中呢?

     首先,解决jQuery对于参数序列化的问题:

     1 /*对象序列化为字符串*/
     2 String.toSerialize = function(obj) {
     3     var ransferCharForJavascript = function(s) {
     4         var newStr = s.replace(
     5         /[\x26\x27\x3C\x3E\x0D\x0A\x22\x2C\x5C\x00]/g,
     6         function(c) {
     7             ascii = c.charCodeAt(0)
     8             return '\\u00' + (ascii < 16 ? '0' + ascii.toString(16) : ascii.toString(16))
     9         }
    10     );
    11         return newStr;
    12     }
    13     if (obj == null) {
    14         return null
    15     }
    16     else if (obj.constructor == Array) {
    17         var builder = [];
    18         builder.push("[");
    19         for (var index in obj) {
    20             if (typeof obj[index] == "function"continue;
    21             if (index > 0) builder.push(",");
    22             builder.push(String.toSerialize(obj[index]));
    23         }
    24         builder.push("]");
    25         return builder.join("");
    26     }
    27     else if (obj.constructor == Object) {
    28         var builder = [];
    29         builder.push("{");
    30         var index = 0;
    31         for (var key in obj) {
    32             if (typeof obj[key] == "function"continue;
    33             if (index > 0) builder.push(",");
    34             builder.push(String.format("\"{0}\":{1}", key, String.toSerialize(obj[key])));
    35             index++;
    36         }
    37         builder.push("}");
    38         return builder.join("");
    39     }
    40     else if (obj.constructor == Boolean) {
    41         return obj.toString();
    42     }
    43     else if (obj.constructor == Number) {
    44         return obj.toString();
    45     }
    46     else if (obj.constructor == String) {
    47         return String.format('"{0}"', ransferCharForJavascript(obj));
    48     }
    49     else if (obj.constructor == Date) {
    50         return String.format('{"__DataType":"Date","__thisue":{0}}', obj.getTime() - (new Date(197001000)).getTime());
    51     }
    52     else if (this.toString != undefined) {
    53         return String.toSerialize(obj);
    54     }
    55 }
    56 


     jQuery异步请求:

     1  $(function() {
     2             /*按钮点击事件*/
     3             $("#btn_post_test").click(function() {
     4                 var data = [
     5                     { UserId: "11", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming""xiaohong"] },
     6                     { UserId: "22", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming""xiaohong"] },
     7                     { UserId: "33", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming""xiaohong"] }
     8                 ];
     9 
    10                 $.post("Home/Test", { users: String.toSerialize(data) }, function(text) {
    11                     alert(String.toSerialize(text));
    12                 }, "json");
    13             }); 
    14         });


     点击按钮提交数据,监控浏览器,可以发现提交的数据是json对象的序列化后的内容:

     1 POST /Home/Test HTTP/1.1
     2 x-requested-with: XMLHttpRequest
     3 Accept-Language: zh-cn
     4 Referer: http://localhost:3149/test.html
     5 Accept: application/json, text/javascript, */*
     6 Content-Type: application/x-www-form-urlencoded
     7 Accept-Encoding: gzip, deflate
     8 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)
     9 Host: localhost:3149
    10 Content-Length: 501
    11 Connection: Keep-Alive
    12 Cache-Control: no-cache
    13 Cookie: CookieGlobalLoginUserID=16063
    14 
    15 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


     其次,后台服务器处理参数绑定:

     1 using System.Collections.Generic;
     2 using System.Web.Mvc;
     3 using Newtonsoft.Json;
     4 using Newtonsoft.Json.Linq;
     5 
     6 namespace WebOS.Controllers
     7 {
     8     [HandleError]
     9     public class HomeController : Controller
    10     {
    11         /// <summary>
    12         /// 测试方法
    13         /// </summary>
    14         /// <param name="users">用户数据</param>
    15         /// <returns>提交的用户数组</returns>
    16         public ActionResult Test([ModelBinder(typeof(JsonBinder<User>))]List<User> users)
    17         { 
    18             return Json(users, JsonRequestBehavior.AllowGet);
    19         }
    20 
    21     }
    22     /// <summary>
    23     /// 对象实体
    24     /// </summary>
    25     [JsonObject]
    26     public class User
    27     {
    28         [JsonProperty("UserName")]
    29         public UserName Name { getset; }
    30         [JsonProperty("UserId")]
    31         public string UserId { getset; }
    32         [JsonProperty("Keys")]
    33         public List<string> Keys { getset; }
    34 
    35 
    36     }
    37     /// <summary>
    38     /// 对象实体
    39     /// </summary>
    40     [JsonObject]
    41     public class UserName
    42     {
    43         [JsonProperty("FirstName")]
    44         public string FirstName { getset; }
    45         [JsonProperty("LastName")]
    46         public string LastName { getset; }
    47 
    48     }
    49     /// <summary>
    50     /// Json数据绑定类
    51     /// </summary>
    52     /// <typeparam name="T"></typeparam>
    53     public class JsonBinder<T> : IModelBinder
    54     {
    55         
    56         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    57         {
    58             //从请求中获取提交的参数数据
    59             var json = controllerContext.HttpContext.Request.Form[bindingContext.ModelName] as string;
    60             //提交参数是对象
    61             if (json.StartsWith("{"&& json.EndsWith("}"))
    62             {
    63                 JObject jsonBody = JObject.Parse(json);
    64                 JsonSerializer js = new JsonSerializer();
    65                 object obj = js.Deserialize(jsonBody.CreateReader(), typeof(T));
    66                 return obj;
    67             }
    68             //提交参数是数组
    69             if (json.StartsWith("["&& json.EndsWith("]"))
    70             {
    71                 IList<T> list = new List<T>();
    72                 JArray jsonRsp = JArray.Parse(json);
    73 
    74                 if (jsonRsp != null)
    75                 {
    76                     for (int i = 0; i < jsonRsp.Count; i++)
    77                     {
    78                         JsonSerializer js = new JsonSerializer();
    79                         object obj = js.Deserialize(jsonRsp[i].CreateReader(), typeof(T));
    80                         list.Add((T)obj);
    81                     }
    82                 }
    83                 return list;
    84             }
    85             return null;
    86         }
    87     }
    88 }
    89 


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

     

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

     
  • 相关阅读:
    SpringBoot 项目瘦身
    对比两个文本的异同
    Spring 事务不起作用的场景
    Controller 层数据校验实现思路
    Notify 类的实现思路
    backup: 使用 vim 时一定会用到的设置 --for-myself
    exercise: 反射获取指定的属性值 --CSharp
    exercise: 序列化和反序列化Xml --CSharp
    前缀
    华罗庚的数学思想
  • 原文地址:https://www.cnblogs.com/cask118/p/1729737.html
Copyright © 2020-2023  润新知