Jsonp简单认识(后端使用的是asp.net mvc)

一、Jsonp简介:由于浏览器基于安全有同源策略(同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性)机制,所以前端无法使用Ajax来获取来获取其他域名下返回的数据,而Jsonp可以实现跨域访问。

  Jsonp是基于<script>标签不受同源策略限制,可以加载任意地方的JavaScript文件来实现的。Jsonp实现理念就是,和服务端约定好一个函数名,当请求文件时,服务端返回一段JavaScript。这段JavaScript调用了约定好的函数,并且将数据当做参数传入。

二、简单Demo

1、在visual studio新建项目JsonpDemo和项目OtherDomain,项目结构如下

2、在JsonpDemo项目中新增HomeController及其视图,视图中代码如下:

 1 @{
 2     Layout = null;
 3 }
 4 
 5 <!DOCTYPE html>
 6 
 7 <html>
 8 <head>
 9     <meta name="viewport" content="width=device-width" />
10     <title>Index</title>
11 </head>
12 <body>
13     <div>
14         <input type="button" id="getJsonpByHand" value="get jsonp by hand" />
15     </div>
16     <script type="text/javascript" >
17         $("#getJsonpByHand").click(function () {
18        //55157位OtherDomain项目启动后网站的端口
19             CreateScript("http://localhost:55157/home/somejsonp?");
20         })
21         function CreateScript(src) {
22             $("<script><//script>").attr("src", src).appendTo("body")
23         }
24      //myCallBack就是与后端约定好的函数
25         function myCallBack(data) {
26             console.log(data);
27         }
28     </script>
29 </body>
30 </html>
View Code

3、在OtherDomain项目中新增HomeController及其视图,HomeController中代码如下:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace OtherDomain.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult SomeJsonp()
        {
            return new ContentResult()
            {
                //myCallBack为服务端与前端约定好的函数
                Content = "myCallBack(" + JsonConvert.SerializeObject(new { Name = "Tom", Age = 23 }) + ")",
                ContentType = "text/html"
            };
        }

    }
}
View Code

4、启动两个项目,点击JsonpDemo项目页面中的按钮,谷歌浏览器控制台下看到

三、对上面Demo做一下简单优化,可以通过前端来指定与服务器约定的函数

1、修改JsonpDemo项目index.cshtml页面中,按钮点击事件下CreateScript方法传入参数为:http://localhost:55157/home/somejsonp?callback=myCallBack 也就是加上一个URL参数

2、修改OtherDomain项目下HomeController.cs中SomeJsonp方法如下:

        public ActionResult SomeJsonp()
        {
            string func = Request.Params["callback"];
            return new ContentResult()
            {
                Content = func+"(" + JsonConvert.SerializeObject(new { Name = "Tom", Age = 23 }) + ")",
                ContentType = "text/html"
            };
        }

四、通过jQuery使用Jsonp实现跨域请求

1、继续沿用上面两个项目,修改JsonpDemo项目index.cshtml页面代码,新增一个按钮,并实现其click事件相关代码,如下:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
</head>
<body>
    <div>
        <input type="button" id="getJsonpByHand" value="get jsonp by hand" />
         <input type="button" id="getJsonpByJquery" value="get jsonp by jquery" />
    </div>
    <script type="text/javascript" >
        $("#getJsonpByHand").click(function () {
            CreateScript("http://localhost:55157/home/somejsonp?callback=myCallBack");
        })
        function CreateScript(src) {
            $("<script><//script>").attr("src", src).appendTo("body")
        }
        $("#getJsonpByJquery").click(function () {
            $.ajax({
                // url: 'http://localhost:55157/home/somejsonp?callback=myCallBack',
                url: 'http://localhost:55157/home/somejsonp',
                dataType: "jsonp",
                jsonp: "callback",
                success: function (data) {
                    console.log(data)
                    var a=123;
                    var b=2;
                    var c=35;
                }
            })
        })
        //function myCallBack(data) {
        //    console.log(data);
        //}
    </script>
</body>
</html>
View Code

注意上面ajax参数dataType为jsonp,jsonp为callback

2、OtherDomain下HomeController.cs文件SomeJsonp代码和第三个里面代码一样,如下:

  public ActionResult SomeJsonp()
        {
            string func = Request.Params["callback"];
            return new ContentResult()
            {
                Content = func + "(" + JsonConvert.SerializeObject(new { Name = "Tom", Age = 23 }) + ")",
                ContentType = "text/html"
            };
        }
View Code

3、运行两个项目,点击“get jsonp by jquery”按钮,可以在谷歌浏览器控制台下看到同样结果

4、注意:如果前端代码传入callback参数,那么前端也要自己实现相应参数的函数。如果没有传入,其实jQuery自己会默认传入并自己实现。

五、扩展:在OtherDomain项目下,简单自定义JsonpResult类,代码如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace OtherDomain
 8 {
 9     public class JsonpResult : JsonResult
10     {
11         private const string CALLBACK_QUERYSTRING = "callback";
12         //private const string CALLBACK_CONTENTTYPE = "application/x-javascript";
13         private const string CALLBACK_CONTENTTYPE = "text/javascript";
14 
15         public override void ExecuteResult(ControllerContext controllerContext)
16         {
17             if (controllerContext != null)
18             {
19                 var request = controllerContext.HttpContext.Request;
20                 object callback = request[CALLBACK_QUERYSTRING];
21                 if (callback == null)
22                 {
23                     controllerContext.RouteData.Values.TryGetValue(CALLBACK_QUERYSTRING, out callback);
24                 }
25 
26                 var hasCallback = !string.IsNullOrWhiteSpace(callback == null ? "" : callback as string);
27                 if (hasCallback)
28                 {
29                     SetContentTypeIfEmpty();
30                     var response = controllerContext.HttpContext.Response;
31                     response.Write(callback);
32                     response.Write("(");
33                     base.ExecuteResult(controllerContext);
34                     response.Write(")");
35                 }
36                 else
37                 {
38                     base.ExecuteResult(controllerContext);
39                 }
40             }
41         }
42 
43         private void SetContentTypeIfEmpty()
44         {
45             if (string.IsNullOrWhiteSpace(base.ContentType))
46             {
47                 base.ContentType = CALLBACK_CONTENTTYPE;
48             }
49         }
50     }
51 
52     public static class ContollerExtensions
53     {
54         public static JsonpResult Jsonp(this Controller controller, object data, JsonRequestBehavior behavior = JsonRequestBehavior.DenyGet)
55         {
56             JsonpResult result = new JsonpResult();
57             result.Data = data;
58             result.JsonRequestBehavior = behavior;
59             return result;
60         }
61     }
62 }
JsonpResult及ContollerExtensions

如果想要很好的结合到controller中,需要写如上ContollerExtensions的Controller的扩展方法

在OtherDomain项目下,需要修改SomeJsonp方法:

      public ActionResult SomeJsonp()
        {
            return this.Jsonp(new
            {
                Name= "Tom",
                Age=23
            }, JsonRequestBehavior.AllowGet);
        }

 

转载于:https://www.cnblogs.com/hujiapeng/p/4914335.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值