跨域访问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 跨域 >>>>>>>>>>>> ...
随机推荐
- HTML页面之间的参数传递
HTML 与 HTML 的跳转中如何在HTML之中实现参数的传递?主要代码如下:request为方法名称,params 为要获取的参数. function request(params) { var ...
- Kubeadm证书过期时间调整
kubeadm 默认证书为一年,一年过期后,会导致api service不可用,使用过程中会出现:x509: certificate has expired or is not yet valid. ...
- 剑指offer:数组中的逆序对
题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%100 ...
- Java多线程的Semaphore
Semaphore 信号量, 在多线程应用中, 用来控制同时访问某个特定资源的操作数量, 或者同时执行某个指定操作的数量, 还可以用来实现某种资源池限制, 或者对容器施加边界. 简单地说, Semap ...
- Springboot属性加载与覆盖优先级与SpringCloud Config Service配置
参考官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config. ...
- thinkphp3.2源码(错误和异常处理)
写在前面:tp3.2中每次载入入口文件时都会进行错误和异常的捕获,解读这一部分代码可以对以后的优化很有好处. 处理概览: 错误捕获与处理: 致命错误捕获: 我们尝试在 Home/ ...
- 案例:使用BeautifuSoup4的爬虫
使用BeautifuSoup4解析器,将招聘网页上的招聘单位名称存储出来.其他信息可类似爬取即可 # -*- coding:utf-8 -*- from bs4 import BeautifulSou ...
- Laya的对象唯一标识
Egret中是obj.hashcode Laya中是obj["$_GID"]
- packaged_task
/** @file packaged_task.cpp * @note * @brief * @author * @date 2019-8-15 * @note * @history * @warni ...
- [图片问答]LODOP打印的行间距字间距
LODOP可以打印纯文本,也可以是超文本,关于哪些打印项是纯文本,哪些打印项是超文本,之前有博文相关介绍:LODOP中的纯文本和超文本打印项. 之前的关于纯文本的行间距字间距介绍:Lodop设置文本项 ...