Mvc 前台使用getJSON异步获取数据的问题
客户端代码:
$(function () {
$.getJSON("/Test/GetList?t=" + new Date(), function (data) {
$("#list").html("");
var list = "";
if (data[0] != null) {
for (var i in data) {
list = list + "<li><a href=\"{$url}\">{$title}</a></li>";
list = list.replace("{$url}", data[i].Url);
list = list.replace("{$title}", data[i].Title);
}
}
$("#list").html(list);
});
})
服务器端代码:
return Json(result.Status, JsonRequestBehavior.AllowGet);
问题:
当我们在页面中引入jquery.validate.min.js时,以上的客户端脚本无法正常执行(每次会触发getJSON请求,但是无法执行function(data){}回调函数)
分析:
先从客户端开始,首先jquery的getJSON方法使用的是动态解析服务器端返回的脚本,eg:客户端实际请求过程可能产生如下的url :http://localhost:31031/Test/GetList?callback=jQuery15104825509083328083_1312943593594&_=1312943593716
注意粗体部分 这部分是自动产生的,它是客户端回调的时候要执行的方法的名称,这部分参数会被提交到服务器端,正常情况下该部分参数会被提交到服务器端,服务器端获取这部分信息
作为返回值的一部分,然后服务器端产生要回传给客户端的数据后,组合两部分数据形成最后的数据,这个数据会被客户端解析成js串动态执行,现在问题出现了,我们的服务器端mvc(当前使用版本3)的:Json()是如何执行的?实际他不会处理我们传递过来的callback=xx部分的参数,而是直接用我们要返回给客户端的数据去序列化成json串返回,也就是说他返回的根本不是一个客户端可以动态执行的:function,这也正是前面说到的为什么function(data)回调函数没有被执行的原因。
解决办法:
1.重写Json类的ExecuteResult(ControllerContext context);
2.不要使用jquery的getJSON(),可以使用get(),post(),ajax()等方法代替;
3.修改jquery.validate.js中相关部分代码,参考[1]
参考文档: [2]
兄弟篇:关于跨域的摘录-JavaScript跨域总结与解决办法
补充资料说明:
Jsonp原理(跨域):
首先在客户端注册一个callback, 然后把callback的名字传给服务器。
此时,服务器先生成 json 数据。
然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
总结,用JSONP要做两件事:
1/请求地址加参数:jsoncallback=?
2/服务器段把jsoncallback的值作为方法名传回来,如JQUET098788(...)
其中 jsonCallback 是客户端注册的,获取跨域服务器上的json数据后,回调的函数。
http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback
这个 url 是跨域服务器取 json 数据的接口,参数为回调函数的名字,返回的格式为
:jsonpCallback({msg:'this is json data'})