注:(原文链接:http://www.cnblogs.com/aehyok/archive/2013/05/18/3085499.html)本文只做收藏,方便以后学习使用
我这边通过原文的理解做了部分修改,没有使用JsonNet.js这个文件对json数据进行序列化,而是直接使用jquery.js的JSON.stringify()
前言
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对于参数序列化的问题: 引用前台处理Js文件,主要是将Json字符串进行处理将其封装到JsonNet.js文件中(原文使用)
String.format =
function
() {
if
(arguments.length == 0)
return
null
;
var
str = arguments[0];
for
(
var
i = 1; i < arguments.length; i++) {
var
re =
new
RegExp(
'\\{'
+ (i - 1) +
'\\}'
,
'gm'
);
str = str.replace(re, arguments[i]);
}
return
str;
}
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);
}
}
|
第二步在页面定义两个按钮事件,并在按钮事件JavaScrpit中进行调用(这一步可以根据实际情况作适当的修改)
@{
ViewBag.Title = "主页";
}
<script src="@Url.Content("~/Scripts/JsonNet.js")" type="text/javascript"></script>
<script type="text/javascript">
function Test() {
var data={UserId:"11",UserName:"2211"};
$.post("../Home/Test", { User: String.toSerialize(data) }, function (data) { alert(String.toSerialize(data)); });
}
function TestList() {
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/TestList", { User: String.toSerialize(data) }, function (data) { alert(String.toSerialize(data)); });
}
</script>
<h2>@ViewBag.Message</h2>
<p>
若要了解有关 ASP.NET MVC 的更多信息,请访问 <a href="http://asp.net/mvc" title="ASP.NET MVC 网站">http://asp.net/mvc</a>。
</p>
<input type="button" value="testList" οnclick="TestList()" />
<input type="button" value=test οnclick="Test()" />
这一步如果引入的是原文的js则是使用String.toSerialize(data),否则使用jquery自带的JSON.stringify(data);
第三步 在后台控制器要使用Json专类来处理,所以要专门下载类库文件进行引用http://json.codeplex.com
下载后解压
各个.net FrameWork的版本文件都有只需要在项目中引用对应的版本即可,这个文件在vs2012里面已经集成直接引用就好了
第四步(这一部分很重要) 就是编写针对Json处理的自动绑定Model, 这个步骤需要引入刚才那个Newtonsoft.Json的命名空间;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
之前有一篇简单的请求参数绑定http://www.cnblogs.com/aehyok/archive/2013/05/01/3052697.html
namespace MvcApplication3.Helper
{
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();
try
{
object obj = js.Deserialize(jsonRsp[i].CreateReader(), typeof(T));
list.Add((T)obj);
}
catch (Exception e)
{
throw e;
}
}
}
return list;
}
return null;
}
}
}
提交的Json可以为单个对象实体类,也可以为实体类的数组List<T>,或者是嵌套的都可以。
//[JsonObject]
public class UserInfo
{
public string UserId{get;set;}
public UserName UserName{get;set;}
public List<string> keys { get; set; }
}
public class UserName
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
[HttpPost]
public ActionResult TestList([ModelBinder(typeof(JsonBinder<UserInfo>))]List<UserInfo> User)
{
List<UserInfo> list = User;
return Json(list, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult Test([ModelBinder(typeof(JsonBinder<UserInfo>))]UserInfo User)
{
UserInfo Userinfo = User;
return Json(User, JsonRequestBehavior.AllowGet);
}
定义了两个简单的实体类并进行关联和上面通过jQuery Ajax提交过来的Json数据格式一致。
主要是通过实现了IModelBinder进行参数化绑定即可。
示例代码下载地址http://url.cn/HRz2JC
最后感谢作者:aehyok