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( 1970 , 0 , 1 , 0 , 0 , 0 )).getTime());
51 }
52 else if ( this .toString != undefined) {
53 return String.toSerialize(obj);
54 }
55 }
56
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( 1970 , 0 , 1 , 0 , 0 , 0 )).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 });
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
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 ///
12 /// 测试方法
13 ///
14 /// 用户数据
15 ///
提交的用户数组
16 public ActionResult Test([ModelBinder( typeof (JsonBinder < User > ))]List < User > users)
17 {
18 return Json(users, JsonRequestBehavior.AllowGet);
19 }
20
21 }
22 ///
23 /// 对象实体
24 ///
25 [JsonObject]
26 public class User
27 {
28 [JsonProperty( " UserName " )]
29 public UserName Name { get ; set ; }
30 [JsonProperty( " UserId " )]
31 public string UserId { get ; set ; }
32 [JsonProperty( " Keys " )]
33 public List < string > Keys { get ; set ; }
34
35
36 }
37 ///
38 /// 对象实体
39 ///
40 [JsonObject]
41 public class UserName
42 {
43 [JsonProperty( " FirstName " )]
44 public string FirstName { get ; set ; }
45 [JsonProperty( " LastName " )]
46 public string LastName { get ; set ; }
47
48 }
49 ///
50 /// Json数据绑定类
51 ///
52 ///
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
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 ///
12 /// 测试方法
13 ///
14 /// 用户数据
15 ///
16 public ActionResult Test([ModelBinder( typeof (JsonBinder < User > ))]List < User > users)
17 {
18 return Json(users, JsonRequestBehavior.AllowGet);
19 }
20
21 }
22 ///
23 /// 对象实体
24 ///
25 [JsonObject]
26 public class User
27 {
28 [JsonProperty( " UserName " )]
29 public UserName Name { get ; set ; }
30 [JsonProperty( " UserId " )]
31 public string UserId { get ; set ; }
32 [JsonProperty( " Keys " )]
33 public List < string > Keys { get ; set ; }
34
35
36 }
37 ///
38 /// 对象实体
39 ///
40 [JsonObject]
41 public class UserName
42 {
43 [JsonProperty( " FirstName " )]
44 public string FirstName { get ; set ; }
45 [JsonProperty( " LastName " )]
46 public string LastName { get ; set ; }
47
48 }
49 ///
50 /// Json数据绑定类
51 ///
52 ///
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/