一、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++的CreateThread实例

    function CreateThread(  lpThreadAttributes: Pointer;           {安全设置}  dwStackSize: DWORD;           ...

  2. m3u8字段意义解析

    m3u8字段意义解析 HLS,Http Live Streaming是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件 ...

  3. python数字图像处理(14):高级滤波

    本文提供更多更强大的滤波方法,这些方法放在filters.rank子模块内. 这些方法需要用户自己设定滤波器的形状和大小,因此需要导入morphology模块来设定. 1.autolevel 这个词在 ...

  4. 导航栏全透明效果, 只保留左右两个按钮, 如何实现?以及关于NavigationController的小问题

    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor clearCo ...

  5. 记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)

    项目上线以来一直存在一个比较揪心的问题,和一个没有信心处理的BUG,那就是在应用程序启动时有可能会导致cpu跑满99%或持续在一个值如50%左右,这样一来对服务器的压力是非常大的,经常出现服务器无法远 ...

  6. 20145215《Java程序设计》课程总结

    20145215<Java程序设计>课程总结 每周读书笔记链接汇总 20145215<Java程序设计>第一周学习总结 20145215<Java程序设计>第二周学 ...

  7. VC++中复制对话框资源 之较好方法之一

    资源对话框的编写有时候较为麻烦,这里我成功实现了这个方法的可用性,具体如下: 碰到模块移植问题了,自己做的对话框类(继承于CDialog)要移植到目标工程中.在网上搜了几个帖子发现都说的很生涩.   ...

  8. android的progressDialog 的使用。android数据异步加载 对话框提示

    在调用的Activity中定义一个全局的 progressDialog 点击按钮的时候调用下面这句 progressDialog = ProgressDialog.show(SearchActivit ...

  9. 一个基于.NET平台的自动化/压力测试系统设计简述

    AutoTest系统设计概述 AutoTest是一个基于.NET平台实现的自动化/压力测试的系统,可独立运行于windows平台下,支持分布式部署,不需要其他配置或编译器的支持.(本质是一个基于协议的 ...

  10. OSX 上安装 Scrapy 的那些坑

    Scrapy 这个爬网框架真心不错,但在OSX上安装总是会出现各种的问题,在这里就作一个收集汇总.我的系统环境是 OS X El Capitan (10.11.1) 首先要保证 pip , virtu ...