在vs中创建一个空的mvc项目,在Controllers文件夹中添加一个控制器CommonController,并在该控制器下添加一个action用于获取服务器时间,代码如下:
public ActionResult getServerTime(string callback)
{
string jsonp = "'serverTime':'{0}'";
DateTime curTime = DateTime.Now;
jsonp = string.Format(jsonp, curTime.ToString("yyyy/MM/dd HH:mm:ss"));
return Content(callback + "({" + jsonp + "})");
}
然后把这个项目运行起来。我这里得到的域名是http://localhost:31187
另外新建一个页面jsonp.html,可以是在本项目中,也可以是在其它地方(为了模拟跨域,最好不要在本项目中)。页面代码如下:
<html>
<head>
<title></title>
<style type="text/css"></style>
<script type="text/javascript" src="js/jquery-1.10.1.js"></script>
<script type="text/javascript">
$(function() {
$.ajax({
url: "http://localhost:31187/common/getServerTime",
type: "get",
data: { callback: "?"},
dataType: "jsonp",
success: function(data) {
var curTime = data.serverTime;
alert(curTime);
},
error: function(a, b, c) {
alert(b);
}
});
});
</script>
</head>
<body>
</body>
</html>
然后打开jsonp.html这个页面,我们就会得到当前服务器的时间,如下图:
这是正确的写法,能够得到数据。但我们在实际用的时候经常会由于这样或那样的原因导致无法成功得到数据,比较经常碰到的错误就是parsererror。parsererror的意思是解析错误,出现这个错误的时候,一般都是服务器有数据返回,但是这个数据无法被解析为json对象。也就是说服务器返回的json格式字符串有问题。这个问题一般是由于自己在写json返回串时的失误造成的,比方说一些逗号和引号。如果把返回串改成如下写法:
string jsonp = "'serverTime':{0}";
再来打开jsonp.html页面,就会得到如下结果:
这说明我们json对象的字段值需要使用引号包起来,字段名上的引号可要可不要,最好是加上。
如果getServerTime这个action没有参数callback,如下:
public ActionResult getServerTime()
{
string jsonp = "'serverTime':'{0}'";
DateTime curTime = DateTime.Now;
jsonp = string.Format(jsonp, curTime.ToString("yyyy/MM/dd HH:mm:ss"));
return Content(jsonp);
}
再运行jsonp.html页面,那么我们同样会得到parsererror这个错误。因为这个callback是jquery在进行跨域请求时生成的一个回调函数名,当页面取得服务器返回的值时,会由该回调函数解析成json对象。所以在返回数据时应该把对整个回调函数的调用进行返回,这个函数需要一个json对象的字符串作为参数,这样才能正常解析。
还有一个比较常见的错误是在写js的时候发生的,很多人在写跨域请求时使用的是post方式,这个是不对的,jsonp格式的请求只能使用get方式提交。使用post方式很有可能也会造成parsererror的错误,但也有可能会正常获取数据。会产生parsererror错误的情况是发起请求的页面和要请求的资源是在同一个项目中,而正常获取数据的页面是在别的域名下发起的请求。但这却并不能说明jsonp可以使用post方式提交,打开chrome浏览器调试页面下的Network,如下图:
我们会神奇的发现,尽管在发起请求时,我们规定了使用post方式提交,但浏览器在实际提交的时候使用的却是get方式。这说明jquery在发起跨域请求时,会作一个内部处理,让请求只能以get方式提交。所以在使用jquery的jsonp格式进行跨域请求时,我们最好都使用get方式提交请求。