使用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,1,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",
{ UserId: "33","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;
}
}
}

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


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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340