跨域访问MVC
using MvcApp.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MvcApp.Controllers
{
[AllowCors("http://localhost:13433", "http://localhost:13435")]
//[AllowCors]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
} public ActionResult Test()
{
var json = new { Name = "Server" };
return Json(json,JsonRequestBehavior.AllowGet);
} }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MvcApp.Filters
{
public class AllowCorsAttribute:ActionFilterAttribute
{
private string[] _domains;
public AllowCorsAttribute()
{
//如果[AllowCors]特性标签没有带域名,那么就从配置文件中读取允许访问的域名,然后将它赋给_domains
//_domains = 这里应该是从配置文件中读出来的所有域名组成的数组
_domains = new string[] { "", "" };
}
public AllowCorsAttribute(params string[] domain)
{
_domains = domain;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var urlReferrer = filterContext.HttpContext.Request.UrlReferrer;
if (urlReferrer != null)
{
var absolutePath = urlReferrer.OriginalString;
var absolutePathFormat = absolutePath.Substring(0, absolutePath.Length - 1);
if (_domains.Contains(absolutePathFormat))
{
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", absolutePathFormat);
}
}
else
{
//如果urlReferrer为空,我理解为自己本地访问(亲自测试,本地访问urlReferrer为null)
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
}
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
filterContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
base.OnActionExecuting(filterContext);
}
}
}
@{
ViewBag.Title = "Index";
} <h2>Index</h2> <script type="text/javascript">
$.ajax({
url: 'http://localhost:24102/Home/Test',
type: 'Post',
success: function (data, textStatus) {
alert(data.Name);
},
error:function(XMLHttpRequest, textStatus, errorThrown){
alert(XMLHttpRequest.state);
} })
</script>
-------------------------------------------------------------------------------------
JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。
1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;
2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);
3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;
4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
如果对于callback参数如何使用还有些模糊的话,我们后面会有具体的实例来讲解。
namespace MvcApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
string callback = this.Request["callback"]; //获取回调函数的名称,的到showMessage
string json = "{\"name\":\"server\"}";
this.Response.Write(callback + "(" + json + ")");
return new EmptyResult();
}
}
}
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script>
function showMessage(result) {
alert(result.name) //运行后打印出server
}
</script>
<script src="http://localhost:58382/home/Index?callback=showMessage" type="text/javascript"></script>
</head>
<body>
<div> </div>
</body>
</html>
-----------MvcApp项目优化 (优化服务端) 主要是自定义一个JsonpResult类,这个类继承了JsonResult类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization; namespace MvcApp.Controllers
{
public class HomeController : Controller
{
public JsonpResult IndexTest()
{
return this.Jsonp(new { name = "server JsonpResult" });
}
} public class JsonpResult : JsonResult
{
public static readonly string JsonpCallbackName = "callback";
public static readonly string CallbackApplicationType = "application/json";
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new AccessViolationException("context");
} if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) //如果不允许来自客户端的Get请求,并且请求类型是Get
{
throw new AccessViolationException();
}
var response = context.HttpContext.Response;
if (!string.IsNullOrEmpty(ContentType)) //这个ContentType是获取或设置内容的类型。它是JsonResult类中的一个属性
{
response.ContentType = ContentType; //设置响应内容的类型
}
else
{
response.ContentType = CallbackApplicationType; //设置响应内容的类型
}
if (ContentEncoding != null)
{
response.ContentEncoding = this.ContentEncoding;//设置响应内容的编码
} if (Data != null) //这个Data是JsonResult类中的一个属性
{
string buffer;
var request = context.HttpContext.Request;
var serializer = new JavaScriptSerializer();
if (request[JsonpCallbackName] != null) //获取回调函数名称(即:获取这个<script src="http://localhost:58382/home/IndexTest?callback=showMessage" type="text/javascript"></script>链接上的callback的值,即获取showMessage)
{
buffer = String.Format("{0}({1})", request[JsonpCallbackName], serializer.Serialize(Data));//首先根据callback获取获取函数名,然后传入json字符串作为函数参数
}
else
{
buffer = serializer.Serialize(Data);
}
response.Write(buffer);
}
}
} /// <summary>
/// Controller控制器类的扩展方法,即:Controller控制器下扩展一个Jsonp方法,这个方法带一个object类型的参数
/// </summary>
public static class ControllerExtension
{
public static JsonpResult Jsonp(this Controller controller, object data)
{
JsonpResult result = new JsonpResult()
{
Data = data,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return result;
}
}
}
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script>
function showMessage(result) {
alert(result.name) //打印出:server JsonpResult
}
</script>
<script src="http://localhost:58382/home/IndexTest?callback=showMessage" type="text/javascript"></script>
</head>
<body>
<div> </div>
</body>
</html
案例:二
直接通过ajax进行跨域请求数据(将dataType的值设为jsonp)
这种方式其中本质也是和案例一是一样的。都是通过Get请求
它最终也是通过请求 http://localhost:58382/home/Index?callback=jsonpCallback&_=1481277739025 这个地址,然后服务端拿到callback这个回调函数,然后返回 jsonpCallback({"name":"Server"}) 这样的一个函数,这样我们在本地定义的jsonpCallback函数就可以使用了。这样功能跨域就实现了
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script src="~/Scripts/jquery-1.8.2.js"></script>
</head>
<body>
<div> </div>
</body>
</html>
<script type="text/javascript">
$.ajax({
url: 'http://localhost:58382/home/Index', //请求的url dataType: "jsonp", //将请求类型设为值jsonp //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonp: "callback", //服务端会通过HttpContext.Request["callback"]; 拿到jsonpCallback这个回调函数的名称 jsonpCallback: "jsonpCallback", //自定义的jsonp回调函数名称"jsonpCallback",返回的json也必须有这个函数名称 success: function (json) {
console.log(json);
alert(json.name);
},
error: function (xhr, status, error)
{ console.log(xhr); }
});
</script>
<pre snippet_file_name="blog_20161209_5_7492657" code_snippet_id="2039637"></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
跨域访问MVC的更多相关文章
- Angular2中对ASP.NET MVC跨域访问
应用场景 项目开发决定使用angular2进行前后端分离开发,由我负责后端服务的开发,起初选择的是web api进行开发.对跨域访问通过API中间件+过滤器对跨域访问进行支持.开发一段后,通知需要移植 ...
- 【转载】ASP.NET MVC设置允许跨域访问
默认情况下,浏览器端发送Ajax请求一般被禁止跨域访问,如A域名网站访问B域名网站的请求会被终止,在ASP.NET MVC项目中,我们可以配置相应的设置项,允许网站的接口跨域访问,主要需要设置Acce ...
- Spring MVC 4.2 CORS 跨域访问
跨站 HTTP 请求(Cross-site HTTP request)是指发起请求的资源所在域不同于该请求所指向资源所在的域的 HTTP 请求.比如说,域名A(http://domaina.examp ...
- ASP.NET MVC & WebApi 中实现Cors来让Ajax可以跨域访问 (转载)
什么是Cors? CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpReq ...
- System.Web.Http.Cors配置跨域访问的两种方式
System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心 ...
- ajax跨域访问 java controller 和 cxf(webservice) 配置方式(CORS)
1. controller跨域访问,配置方式 重点在这里: <mvc:cors> <mvc:mapping path="/*" allowed-origins=& ...
- Ajax跨域访问解决办法
方法1. jsonp实现ajax跨域访问示例 jsp代码: <body> <input type="button" onclick="testJsonp ...
- 跨域访问之JSONP
跨域 在平常的工作中常常会遇到A站点的需要访问B站点的资源. 这时就产生了跨域访问. 跨域是指从一个域名的网页去请求另一个域名的资源.浏览器遵循同源策略,不允许A站点的Javascript 读取B站点 ...
- SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域
SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域 >>>>>>>>>>>> ...
随机推荐
- hadoop jps 出现空指针错误
在hadoop中安装jdk软件以后出现如下问题: 错误描述 [xxx@localhost jdk1..0_181]$ ./bin/jps Exception in thread "main& ...
- Echarts的简单入门
5 分钟上手 ECharts 获取 ECharts 你可以通过以下几种方式获取 ECharts. 从官网下载界面选择你需要的版本下载,根据开发者功能和体积上的需求,我们提供了不同打包的下载,如果你在体 ...
- 【2019.11.27】SDN上机第5次作业
参考资料: https://www.cnblogs.com/zzqsss/p/11924685.html 问答环节 描述官方教程实现了一个什么样的交换机功能? Ryu是一个基于组件的软件定义的网络框架 ...
- python离线包下载地址
https://pypi.org/project/pdfconv/ https://pypi.org/search/?q=major&o=
- vue---封装request做数据请求
参考文章: https://www.cnblogs.com/qiuchuanji/p/10048805.html https://www.cnblogs.com/XHappyness/p/999387 ...
- win 10 系统安装后的配置
win10图片恢复默认照片查看器 1. 搜索栏”放大文本大小“ 调整字体大小 2. 桌面显示 我的电脑: 3. 关闭不必要的动画,ctrl+r,输入:control ,打开控制面板
- SSM框架新特性关于用Java配置类完全代替XML
项目目录结构 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法, 这些方法将会被AnnotationConf ...
- python web开发——django学习(二)第一个django网站运行成功
1.写message_form.html <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- 使用ObjectARX 2012向导生成的自定义实体类无法捕捉的问题解决方式
使用ObjectARX 2012自定实体向导的时候,获取捕捉点的重写函数的向导中模板有点问题, C:\Program Files (x86)\Autodesk\ObjectARX 2019 Wizar ...
- poj 2775 文件结构“图"
总时间限制: 1000ms 内存限制: 65536kB 描述 在计算机上看到文件系统的结构通常很有用.Microsoft Windows上面的"explorer"程序就是这样的一个 ...