文档章节

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

h
 hujiapeng
发布于 2016/12/28 09:41
字数 1120
阅读 1
收藏 0

一、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);
        }

 

© 著作权归作者所有

h
粉丝 0
博文 100
码字总数 60569
作品 0
海淀
私信 提问
【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--目录(8/8 完结)

为什么要做这个 在使用nodejs开发过程中,总是发现需要做很多重复性的体力劳动,且因为自身是服务端程序员出身,感觉有一些服务端好的东西其实可以在nodejs上得到应用并能提高一些开发工作效...

czd890
2018/07/26
0
0
[asp.net mvc 奇淫巧技] 06 - 也许你的项目同一个用户的请求都是同步的

一、感慨 很久前看到一篇博客中有句话大致的意思是:“asp.net 程序性能低下的主要原因是开发人员技术参差不齐”,当时看到这句话不以为然,然而时间过的越久接触的.net 开发人员越多就越认同...

Emrys5
04/28
0
0
ASP.NET MVC 2 RC 发布

ASP.NET MVC在现有的ASP.NET 运行时的基础上提供了一个新的MVC框架。开发人员可以用MVC设计模式来构建Web应用,做到清晰的概念分离(UI或者视图与业务应用逻辑分离, 应用逻辑和后端数据分离...

红薯
2009/12/17
557
1
Asp.Net MVC 使用 Ajax

Asp.Net MVC 使用 Ajax Ajax 简单来说Ajax是一个无需重新加载整个网页的情况下,可以更新局部页面或数据的技术(异步的发送接收数据,不会干扰当前页面)。 Ajax工作原理 Ajax使浏览器和服务...

JoeSnail
2017/11/13
0
0
MVC 框架--ASP.NET MVC

ASP.NET MVC在现有的ASP.NET 3.5运行时的基础上提供了一个新的MVC框架。开发人员可以用MVC设计模式来构建Web应用,做到清晰的概念分离(UI或者视图与业务应用逻辑分离, 应用逻辑和后端数据分...

匿名
2009/04/03
57.8K
1

没有更多内容

加载失败,请刷新页面

加载更多

MySql双主架构原理

在企业中,一般系统架构的瓶颈会出现在数据库这一部分,mysql主从架构在很大程度上解决了这部分瓶颈,但是在mysql主从同步的架构也存在很多问题;比如:1.关于数据写入部分(也就是主库)往往很难做...

xiaomin0322
28分钟前
0
0
分布式系统中一致性哈希

问题场景 近年来B2C、O2O等商业概念的提出和移动端的发展,使得分布式系统流行了起来。分布式系统相对于单系统,解决了流量大、系统高可用和高容错等问题。功能强大也意味着实现起来需要更多...

Java领航员
30分钟前
0
0
接口限流算法:漏桶算法和令牌桶算法

漏桶算法 漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。这一点和线程池原理是很相似的。 把请求比作是水,水来了都先放进桶里,并以限定...

铁骨铮铮
37分钟前
5
0
Android 生成二维码工具类

/** * 生成条形码和二维码的工具 */public class ZXingUtils { /** * 生成二维码 要转换的地址或字符串,可以是中文 * * @param url * @param width ...

lanyu96
42分钟前
1
0
谈谈lucene的DocValues特性之SortedNumericDocValuesField

前面已经介绍过NumericDocValuesField,这里想强调一下SortedNumericDocValuesField是针对同一篇文档中一键多值的情况进行排序的,换句话说不同文档的同一字段值可以乱序。核心的写入流程与谈...

FAT_mt
50分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部