使用jQuery向asp.net Mvc傳遞復雜json數(shù)據(jù)-ModelBinder篇
更新時間:2010年05月07日 22:26:13 作者:
jQuery提供的ajax方法能很方便的實現(xiàn)客戶端與服務器的異步交互,在asp.net mvc 框架使用jQuery能很方便地異步獲取提交數(shù)據(jù),給用戶提供更好的體驗!
調用jQuery的ajax方法時,jQuery會根據(jù)post或者get協(xié)議對參數(shù)data進行序列化;
如果提交的數(shù)據(jù)使用復雜的json數(shù)據(jù),例如:
{userId:32323,userName:{firstName:"李",lastName:"李大嘴"}}
那么服務器是無法正常接收到完整的參數(shù),因為jQuery對data的序列化,是使用了鍵值對拼裝的方式;
參數(shù)拼裝成 userId=32323&userName=object ; userName所指向的對象被序列化成字符串"object"
如何才能把一個復雜的object對象提交到后臺的action參數(shù)中呢?
首先,解決jQuery對于參數(shù)序列化的問題:
/*對象序列化為字符串*/
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");
});
});
點擊按鈕提交數(shù)據(jù),監(jiān)控瀏覽器,可以發(fā)現(xiàn)提交的數(shù)據(jù)是json對象的序列化后的內(nèi)容:
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
其次,后臺服務器處理參數(shù)綁定:
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">用戶數(shù)據(jù)</param>
/// <returns>提交的用戶數(shù)組</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數(shù)據(jù)綁定類
/// </summary>
/// <typeparam name="T"></typeparam>
public class JsonBinder<T> : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
//從請求中獲取提交的參數(shù)數(shù)據(jù)
var json = controllerContext.HttpContext.Request.Form[bindingContext.ModelName] as string;
//提交參數(shù)是對象
if (json.StartsWith("{") && json.EndsWith("}"))
{
JObject jsonBody = JObject.Parse(json);
JsonSerializer js = new JsonSerializer();
object obj = js.Deserialize(jsonBody.CreateReader(), typeof(T));
return obj;
}
//提交參數(shù)是數(shù)組
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;
}
}
}
前端獲取到后臺返回的數(shù)據(jù),結果就是用戶提交的數(shù)據(jù):

后臺json反序列化使用了Newtonsoft.Json 組件,有關資料請參考:http://james.newtonking.com/
如果提交的數(shù)據(jù)使用復雜的json數(shù)據(jù),例如:
{userId:32323,userName:{firstName:"李",lastName:"李大嘴"}}
那么服務器是無法正常接收到完整的參數(shù),因為jQuery對data的序列化,是使用了鍵值對拼裝的方式;
參數(shù)拼裝成 userId=32323&userName=object ; userName所指向的對象被序列化成字符串"object"
如何才能把一個復雜的object對象提交到后臺的action參數(shù)中呢?
首先,解決jQuery對于參數(shù)序列化的問題:
復制代碼 代碼如下:
/*對象序列化為字符串*/
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");
});
});
點擊按鈕提交數(shù)據(jù),監(jiān)控瀏覽器,可以發(fā)現(xiàn)提交的數(shù)據(jù)是json對象的序列化后的內(nèi)容:
復制代碼 代碼如下:
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
其次,后臺服務器處理參數(shù)綁定:
復制代碼 代碼如下:
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">用戶數(shù)據(jù)</param>
/// <returns>提交的用戶數(shù)組</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數(shù)據(jù)綁定類
/// </summary>
/// <typeparam name="T"></typeparam>
public class JsonBinder<T> : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
//從請求中獲取提交的參數(shù)數(shù)據(jù)
var json = controllerContext.HttpContext.Request.Form[bindingContext.ModelName] as string;
//提交參數(shù)是對象
if (json.StartsWith("{") && json.EndsWith("}"))
{
JObject jsonBody = JObject.Parse(json);
JsonSerializer js = new JsonSerializer();
object obj = js.Deserialize(jsonBody.CreateReader(), typeof(T));
return obj;
}
//提交參數(shù)是數(shù)組
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;
}
}
}
前端獲取到后臺返回的數(shù)據(jù),結果就是用戶提交的數(shù)據(jù):

后臺json反序列化使用了Newtonsoft.Json 組件,有關資料請參考:http://james.newtonking.com/
您可能感興趣的文章:
- SpringMVC實現(xiàn)前端后臺交互傳遞數(shù)據(jù)
- ASP.NET MVC從控制器傳遞數(shù)據(jù)到視圖的四種方式詳解
- springMVC框架下JQuery傳遞并解析Json數(shù)據(jù)
- Spring MVC 學習 之 - URL參數(shù)傳遞詳解
- jsp 顯示springmvc modelmap傳遞的對象詳細介紹
- SpringMVC框架下JQuery傳遞并解析Json格式的數(shù)據(jù)是如何實現(xiàn)的
- ASP.NET中MVC傳遞數(shù)據(jù)的幾種形式總結
- Ruby on Rails中MVC結構的數(shù)據(jù)傳遞解析
- ASP.NET中MVC從后臺控制器傳遞數(shù)據(jù)到前臺視圖的方式
- MVC頁面之間參數(shù)傳遞解析
相關文章
jQuery選擇器源碼解讀(五):tokenize的解析過程
這篇文章主要介紹了jQuery選擇器源碼解讀(五):tokenize的解析過程,本文用詳細的注釋解讀了tokenize方法的解析過程,需要的朋友可以參考下2015-03-03jQuery仿gmail實現(xiàn)fixed布局的方法
這篇文章主要介紹了jQuery仿gmail實現(xiàn)fixed布局的方法,涉及jQuery操作頁面元素屬性的相關技巧,需要的朋友可以參考下2015-05-05jQuery源碼分析之jQuery中的循環(huán)技巧詳解
這篇文章主要介紹了jQuery源碼中的循環(huán)技巧,包括各類選擇、判斷、遍歷等等操作,非常實用的技巧,需要的朋友可以參考下2014-09-09以jQuery中$.Deferred對象為例講解promise對象是如何處理異步問題
Promises是一種令代碼異步行為更加優(yōu)雅的抽象,它很有可能是JavaScript的下一個編程范式,一個Promise即表示任務結果,無論該任務是否完成。本文以jQuery中$.Deferred對象為例講解promise對象是如何處理異步問題,需要的朋友參考下2015-11-11EasyUI學習之DataGird分頁顯示數(shù)據(jù)
這篇文章主要介紹了EasyUI學習之DataGird分頁顯示數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12