最近在新公司的项目里面经常用到JQuery的getJSON方法和后台程序进行交互,所以特意来总结一下,以备以后的项目的需要。
jQuery中常用getJSON来调用并获取远程的JSON字符串,将其转换为JSON对象,如果成功,则执行回调函数。原型如下:
jQuery.getJSON( url, [data], [callback] )
url:必需 规定将请求发送的哪个 URL
data : (可选) 规定连同请求发送到服务器的key/value数据
callback: (可选) 载入数据成功时的回调函数
例如:
function LoginSubmit(memberDomain) {
if (document.getElementById("Account").value == "" || document.getElementById("Password").value == "") {
alert("用户名或密码不能为空?");
} else {
$.getJSON(memberDomain + "/Login/LoginIndex?jsoncallback=?", {
account: document.getElementById("Account").value,
password: document.getElementById("Password").value,
rnum: Math.random()
}, function (result) {
if (result.IsSuccess) {
loginPanelInit(memberDomain);
}
else {
alert("登录不成功!");
}
});
}
}
上面getJSON url部分的memberDomain表示域名,getJSON支持跨域调用,Login表示ASP.NET MVC里面控制器Controller的名字,LoginIndex表示Action的名字.URL后面跟的jsoncallback=?表示该请求是JQuery的JSONP请求.
JQuery官方的网站对getJSON方法的英文解释说明了这一点。
If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.
JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。这种跨域的通讯方式称为JSONP。
很明显,JSONP是一种脚本注入(Script Injection)行为,需要特别注意其安全性。
jQuery对JSONP请求的封装方式很值得提倡:
$.getJSON(url, params + "&jsoncallback=?", function(json){
/* do something */
});
用jsoncallback作为服务器端支持的标准jsonp参数,而每次执行这个方法都会用时间戳生成一个唯一的全局函数名,替换这个“?”,这个细节被封装到黑盒里,使用者不必了解,可以像普通的ajax请求一样,用匿名的回调函数作为最末尾的参数(这是jquery强调的风格),这种语法糖(syntactic sugar)的作用绝对不仅仅是让前端开发人员可以偷懒而已,对代码的可读性,兼容性和今后的维护都有好处。
Jsonp原理:
首先在客户端注册一个callback, 然后把callback的名字传给服务器。
此时,服务器先生成 json 数据。
然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
注意:
1.运用JQuery的进行跨域调用时请求地址一定要有 jsoncallback=? ,例如我请求 百度,传一个参数userName=123,应该这样写:http://www.baidu.com?userName=123&jsoncallback=? ,如果我不传参数userName,应该这样写:http://www.baidu.com?jsoncallback=?
2、第二个参数一定要是json格式键/值对的格式。例:{ "email": ""}
3、回调函数,您请求的地址需要返回数据,返回的数据必须是严格的json格式的数据,还需要用参数jsoncallback加小括号包裹jsoncallback(json格式的数据),否则就会出现回调函数不会执行的问题。
如下面控制器返回的数据是就是这种格式jsoncallback(SerializeHelper.JsonSerialize(viewData))。
return Content(string.Format("{0}({1})", jsoncallback, SerializeHelper.JsonSerialize(viewData)), "text/plain", System.Text.Encoding.UTF8);
JQuery跨域调用的后台方法:
public ActionResult LoginIndex(string account, string password)
{
string jsoncallback = Request.QueryString["jsoncallback"];
bool tag = true;
loginInfo dto = new loginInfo();
dto.Account = account;
dto.AccountError = "";
JsonViewData viewData = new JsonViewData() { IsSuccess = false, ErrorMessage = "登录失败" };
password = CryptographyHelper.MD5(CryptographyHelper.MD5(password));
MembershipDTO mdto = MembershipBiz.Instance.Login(account, password);
if (mdto != null)
{
if (mdto.Status >= 0)
{
string ip = System.Web.HttpContext.Current.Request.UserHostAddress;
MembershipBiz.Instance.LogionUpdate(mdto.MembershipId, ip);
UpdateCredit(mdto.MembershipId, ip);
}
else
{
dto.AccountError = "该用户不存在";
tag = false;
viewData.IsSuccess = false;
}
}
else
{
dto.AccountError = "帐号或者密码错误";
tag = false;
viewData.IsSuccess = false;
}
if (tag)
{
Security.Authentication.Authenticate(account, password, false);
viewData.IsSuccess = true;
return Content(string.Format("{0}({1})", jsoncallback, SerializeHelper.JsonSerialize(viewData)), "text/plain", System.Text.Encoding.UTF8);
}
else
{
viewData.IsSuccess = false;
return Content(string.Format("{0}({1})", jsoncallback, SerializeHelper.JsonSerialize(viewData)), "text/plain", System.Text.Encoding.UTF8);
}
}
JQuery getJSON的等价形式$.ajax()或者JQuery.ajax().这种形式相比$.getJSON形式更加的具体,通过设置不同的参数控制起来更加的灵活。比如在某些特殊情况下可以将请求由异步改为同步async: false,请求的类型可以设置为"post"等。
如下所示:
function GetSupplyNum(id) {
var childnum = "";
jQuery.ajax({
type: "get",
async: false,
url: "/Default1/GetSupplyCountByCategory",
data: 'id=' + id + '',
contentType: "text",
dataType: "json",
cache: false,
success: function (data) {
childnum = childnum + data;
}
});
return childnum;
}