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

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

二、简单Demo

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

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

 @{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
<input type="button" id="getJsonpByHand" value="get jsonp by hand" />
</div>
<script type="text/javascript" >
$("#getJsonpByHand").click(function () {
       //55157位OtherDomain项目启动后网站的端口
CreateScript("http://localhost:55157/home/somejsonp?");
})
function CreateScript(src) {
$("<script><//script>").attr("src", src).appendTo("body")
}
     //myCallBack就是与后端约定好的函数
function myCallBack(data) {
console.log(data);
}
</script>
</body>
</html>

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 = }) + ")",
ContentType = "text/html"
};
} }
}

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 = }) + ")",
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>

注意上面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 = }) + ")",
ContentType = "text/html"
};
}

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

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

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

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace OtherDomain
{
public class JsonpResult : JsonResult
{
private const string CALLBACK_QUERYSTRING = "callback";
//private const string CALLBACK_CONTENTTYPE = "application/x-javascript";
private const string CALLBACK_CONTENTTYPE = "text/javascript"; public override void ExecuteResult(ControllerContext controllerContext)
{
if (controllerContext != null)
{
var request = controllerContext.HttpContext.Request;
object callback = request[CALLBACK_QUERYSTRING];
if (callback == null)
{
controllerContext.RouteData.Values.TryGetValue(CALLBACK_QUERYSTRING, out callback);
} var hasCallback = !string.IsNullOrWhiteSpace(callback == null ? "" : callback as string);
if (hasCallback)
{
SetContentTypeIfEmpty();
var response = controllerContext.HttpContext.Response;
response.Write(callback);
response.Write("(");
base.ExecuteResult(controllerContext);
response.Write(")");
}
else
{
base.ExecuteResult(controllerContext);
}
}
} private void SetContentTypeIfEmpty()
{
if (string.IsNullOrWhiteSpace(base.ContentType))
{
base.ContentType = CALLBACK_CONTENTTYPE;
}
}
} public static class ContollerExtensions
{
public static JsonpResult Jsonp(this Controller controller, object data, JsonRequestBehavior behavior = JsonRequestBehavior.DenyGet)
{
JsonpResult result = new JsonpResult();
result.Data = data;
result.JsonRequestBehavior = behavior;
return result;
}
}
}

JsonpResult及ContollerExtensions

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

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

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

Jsonp简单认识(后端使用的是asp.net mvc)的更多相关文章

  1. Asp.net Mvc模块化开发之“开启模块开发、调试的简单愉快之旅”

    整个世界林林种种,把所有的事情都划分为对立的两个面. 每个人都渴望的财富划分为富有和贫穷,身高被划分为高和矮,身材被划分为胖和瘦,等等. 我们总是感叹,有钱人的生活我不懂;有钱人又何尝能懂我们每天起早 ...

  2. Asp.net Mvc模块化开发之“部分版本部分模块更新(上线)”

    项目开发从来就不是一个简单的问题.更难的问题是维护其他人开发的项目,并且要修改bug.如果原系统有重大问题还需要重构. 怎么重构系统不是本文探讨的问题,但是重构后如何上线部署和本文关系密切.这个大家可 ...

  3. ASP.NET MVC防范CSRF最佳实践

    XSS与CSRF 哈哈,有点标题党,但我保证这篇文章跟别的不太一样. 我认为,网站安全的基础有三块: 防范中间人攻击 防范XSS 防范CSRF 注意,我讲的是基础,如果更高级点的话可以考虑防范机器人刷 ...

  4. Asp.net Mvc模块化开发之分区扩展框架

    对于一个企业级项目开发,模块化是非常重要的. 默认Mvc框架的AreaRegistration对模块化开发真的支持很好吗?真的有很多复杂系统在使用默认的分区开发的吗?我相信大部分asp.net的技术团 ...

  5. Asp.net Mvc模块化开发系列(目录)

    模块化开发是非常重要的,模块化开发是个系统性问题,为此我觉得有必须要写一个系列的文章才能基本说的清楚 那又为什么要写一个目录呢? 其一.是对我昨天承诺写一个系列新的文章的回应 其二.是先写出一个大纲, ...

  6. 7 天玩转 ASP.NET MVC — 第 1 天

    0. 前言正如标题「7 天玩儿转 ASP.NET MVC」所言,这是个系列文章,所以将会向大家陆续推出 7 篇.设想一下,一天一篇,你将从一个愉快的周一开始阅读,然后在周末成为一个 ASP.NET M ...

  7. ASP.NET MVC学习之模型绑定(1)

    一.前言 下面我们将开始学习模型绑定,通过下面的知识我们将能够理解ASP.NET MVC模型的模型绑定器是如何将http请求中的数据转换成模型的,其中我们重点讲述的是表单数据. 二.正文 1.简单类型 ...

  8. 7 天玩转 ASP.NET MVC - 第 1 天

    0. 前言 正如标题「7 天玩儿转 ASP.NET MVC」所言,这是个系列文章,所以将会向大家陆续推出 7 篇.设想一下,一天一篇,你将从一个愉快的周一开始阅读,然后在周末成为一个 ASP.NET ...

  9. AngularJS html5Mode与ASP.NET MVC路由共存

    前言 很久之前便听说AngularJS,非常酷,最近也比较火,我也在持续关注这个技术,只是没有认真投入学习.前不久公司找我们部门做一个OA系统(想省下几万大洋的费用),第一时间便想到AngularJS ...

随机推荐

  1. C语言 文件操作8--fputs()和fgets()

    //fputs()和fgets() #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> # ...

  2. C语言 文件操作7--文件错误处理

    //文件错误处理 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include&l ...

  3. jacob下载问题, Office word 此文件正由另一应用程序或用户使用的解决方法

    http://jingyan.baidu.com/article/75ab0bcbd6682fd6864db2db.html

  4. OAF 中对文字实现html效果及对超级长文本实现默认换行,对只读的messageTextInput中的内容自动换行

    今天遇到一个需求,客户注册页面客户化了一个超级长的注册须知,内容很多.但是样式相对又要做起来好看点. 注册须知的内容使用多个message拼接而成. 老大说rawText支持html样式,于是我想到了 ...

  5. Hello,cnblog‘s world!

    纠结了许久,终于选在这个地方安家.之所以选在这里,是因为这里是个很干净的社区. 之前一直在其他博文网站里发文章,可是越到后来,发现页面广告越来越多.真正对自己有价值的内容越来越少,虽然已经使用过几年了 ...

  6. 结合C++和GDAL实现shapefile(shp)文件的创建和写入

    工具:vs2012+GDAL 2.0 包含头文件: #include "ogrsf_frmts.h" int main() { const char *pszDriverName ...

  7. Linux常用指令---工作

    查看所有用户cat /etc/passwd 复制整个目录cp -ri A/B/* A1/B1/ 若复制过程中询问是否覆盖,输入y按回车 另外若A A1不在同一目录下,最好填绝对路径,就是/xxx/xx ...

  8. [CareerCup] 11.5 Search Array with Empty Strings 搜索含有空字符串的数组

    11.5 Given a sorted array of strings which is interspersed with empty strings, write a method to fin ...

  9. 浅入DNS

    1.DNS是怎么工作的 首先我们可以很简单的理解DNS协议,它就是一个将域名与ip地址进行双向转换的协议,而消息类型只有查询和回应2种类型.那客户端查询域名,是要请求谁呢?答案是域名服务器,现在域名服 ...

  10. Linux下线程池的理解与简单实现

    首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...