一、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. 【转】【Asp.Net】了解使用 ASP.NET AJAX 进行局部页面更新

    简介Microsoft的 ASP.NET 技术提供了一个面向对象.事件驱动的编程模型,并将其与已编译代码的优势结合起来.但其服务器端的处理模型仍存在技术本身所固有的几点不足: 进行页面更新需要往返服务 ...

  2. MySQL主从同步几个文件

    MySQL主从同步:   M锁表 M导出S导入 M解锁 M建同步帐号 S获取点位:产生master.info S开启同步   3306: mysql-bin.0000x mysql-bin.index ...

  3. Linux 网络编程二(Socket创建)

    TCP通信 一个程序使用套接字需要执行4个步骤. --分配套接口和初始化 --连接 --发送或接收数据 --关闭套接字 涉及到的调用包括socket.bind.listen.connect(阻塞线程) ...

  4. 《深入理解计算机系统》 Chapter 7 读书笔记

    <深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...

  5. HoloLens开发手记 - Unity之摄像头篇

    当你穿戴好HoloLens后,你就会处在全息应用世界的中心.当你的项目开启了"Virtual Reality Support"选项并选中了"Windows Hologra ...

  6. 一起写一个Android图片加载框架

    本文会从内部原理到具体实现来详细介绍如何开发一个简洁而实用的Android图片加载缓存框架,并在内存占用与加载图片所需时间这两个方面与主流图片加载框架之一Universal Image Loader做 ...

  7. sql server 2008 数据库的完整性约束

    一.数据库完整性概述   1.数据库的完整性:   ①数据库的完整性是指数据的正确性和相容性 ②数据库完整性是防止不合语义或不正确的数据进入数据库 ③完整性体现了是否真实地反映现实世界   例:  学 ...

  8. Orchard 刨析:Caching

    关于Orchard中的Caching组件已经有一些文章做了介绍,为了系列的完整性会再次对Caching组件进行一次介绍. 缓存的使用 在Orchard看到如下一段代码: 可以看到使用缓存的方法Get而 ...

  9. [JQuery EasyUI系列]简介

    一.jQuery EasyUI是一个基于jQuery的框架,继承了各种用户界面插件. 二.jQuery EasyUI框架提供了创建网页所需的一切,可以轻松建立站点. easyui是一个基于jQuery ...

  10. 每天一个linux命令(20):linux chmod命令

    chmod命令用于改变linux系统文件或目录的访问权限.用它控制文件或目录的访问权限.该命令有两种用法.一种是包含字母和操作符表达式的文字设定法:另一种是包含数字的数字设定法. Linux系统中的每 ...