在web开发中,如果你要在不同域下进行数据异步请求,会出现一个No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”的错误提示。
该提示信息说明,跨域请求是违反了“同源策略”的。
但是在开发中又难免会遇到跨域请求的需求,所以前辈们也是留下了跨域请求数据的方法jsonp跨域请求。
我们以最为典型的Jquery做例子,后台用的asp.net mvc。
我们先构造一个action的返回对象,用于返回jsonp数据
#region JsonResult public class JsonpResult<T> : ActionResult { public T Obj { get; set; } public string CallbackName { get; set; } public JsonpResult(T obj, string callback) { this.Obj = obj; this.CallbackName = callback; } public override void ExecuteResult(ControllerContext context) { var js = new System.Web.Script.Serialization.JavaScriptSerializer(); var jsonp = this.CallbackName + "(" + js.Serialize(this.Obj) + ")"; context.HttpContext.Response.ContentType = "application/json"; context.HttpContext.Response.Write(jsonp); } } #endregion
写一个供前台调用的action ,callback参数是必须的一个参数
public ActionResult AjaxJsonp(string s, string f,string callback) { string result=s+'-'+f; return new JsonpResult<object>(new { result = result }, callback); }
然后我们在前台用Ajax跨域调用该方法(如果是在本地测试,在不同的端口号下即可)
$.ajax({ type: "GET", url: "AjaxJsonp?callback=?", data: { s: '',f:''}, cache: false, error: function () { alert("程序出错,请联系管理员."); }, dataType: "jsonp", jsonp: 'callback', success: function (result) { if (result) { //返回对象处理 } } });
原理:
类似于使用js创建一个script元素,引用的地址就是我们请求的地址。
既然引用了该地址,而我们的地址输出的是:
callback(data);
这就相当于执行了一个函数:callback,并把data传入了这个函数,所以我们就拿到了data;
介绍Ajax jsonp跨域请求的参数说明
- type:请求的类型(get/post),这里需要注意的是,跨域请求只能是Get方式请求,这是因为限制于实现跨域的原理,但你会发现,将type写为post同样能执行,这是为什么呢?
在仔细查看监控的请求方式,其实还是GET方式,这就说明Jquery在内部已经做了处理,所以跨域请求只能是get请求,请求数据量是很有限的。 - url:url后面的callback=?是必须的,Jquery会将?号生成一个随机的名字,用于回调
- data:传递的参数
- cache:是否开启缓存,如果请求的数据是不变的,那么可以开启缓存提高效率
- dataType:一定是jsonp
- jsonp:callback名一般使用默认callback,可自行修改
- error:请求出错时执行
- success:请求成功回调并返回结果数据