一、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. 全面理解HTTP

    URL与URI 我们经常接触到的就是URL了,它就是我们访问web的一个字符串地址,那么URI是什么呢?他们是什么关系呢? URL:uniform resource location 统一资源定位符U ...

  2. C# 将透明图片的非透明区域转换成Region

    以下代码实现将一张带透明度的png图片的非透明部分转换成Region输出 /// <summary> /// 根据图片得到一个图片非透明部分的区域 /// </summary> ...

  3. 微软职位内部推荐-Software Development Engineer 2

    微软近期Open的职位: SDE II Organization Summary: Engineering, Customer interactions & Online (ECO) is l ...

  4. js实现倒计时 类似团购网站

    一.demo与效果展示 为节约时间,我就直接套用了企鹅团的界面作为demo的背景.因为是倒计时,所以需要一个固定的时间,为了n年后,某位仁兄打开demo页面依然在倒计时,所以我把倒计时时间设成了205 ...

  5. 每日一SQL-善用DATEADD和DATEDIFF

    转自:http://www.dotblogs.com.tw/lastsecret/archive/2010/10/04/18097.aspx 上個星期去Tech-Day聽了幾場有趣的課,其中一堂是楊志 ...

  6. Android Support Annotations :安卓注解快速上手

    我们都知道,安卓资源文件都是int类型的ID来保存其引用,通过注解类型,可以让我们在写代码的时候,及时发现参数类型的错误,避免潜在的BUG,如下: 我们通过@LayoutRes指定了参数必须要是R.l ...

  7. Daily English

  8. “未能加载文件或程序集“EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”

    产生原因: 使用nuget管理程序包,同一个解决方案里面有不同版本的Entity Framework,有可能在不同时间安装不同版本的Entity Framework,所以出现这个问题. 解决方案: 1 ...

  9. [bzoj2245][SDOI2011]工作安排(费用流)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2245 分析: 要注意到题目下面说的w是单增的 明显的费用流: 弄个源点S,汇点T S连 ...

  10. [USACO2003][poj2138]Travel Games(dp/最长路)

    http://poj.org/problem?id=2138 题意:给你一些单词和初始单词,在初始单词的任意位置你可以加任意一个字母,使得这个新单词在给的单词中有所出现,然后在这样不断迭代下去,让你求 ...