已经开始学习WebApi有一段时间了,但是可能使用的情况一直停留在一个比较窄的思路里,属于那种有坡度的开发和学习路径。想必大家已经看到过学习陡险这类似的图形,我现在差不多就是这种情况了,感觉自己学习了,会用了。案例习题都懒得去动,已有问题来了,想去弄才发觉自己学的东西都是零呀。悲催了,我的哥。
好了废话不说,今天我们来看一下跨域的问题。
1.什么是跨域问题
至于跨域问题的说法网络是比较多的,我这边只简单说明一下。具体链接我可以提供一个其他博友写的文章,还是不错的,我这里只针对该问题做一个总结和理解吧。
跨域问题:案例:比如http://www.baidu.com (百度)和http://www.sogou.com(搜狗) 两个域名。有一天搜狗说我这边想请求要给百度图片资源里的高清大图,因为搜狗这边没有,又不想自己做一个图片,想坐享其成。然后利用网络请求一个图片。像<img src='http://www.baidu.com/img/big.png'/>,当我们在浏览器的调试工具中,F12打开,在NetWork部分进行跟踪。会出现问题,因为Html5的规范,组织浏览器请求其他域的资源(或许说法不准确,就是这个意思),比如我的域名下有cookie,其他网站请求我的,我能给他吗?当然不行,我的资源我独享。当然这种也没有什么的,只是读取嘛,要是你想改变我的资源呢?比如Post 或Put,做一些不安全的操作,那不是乱套了。这就是跨域的问题来了。比如我真的要请求资源怎么办?比如,公司的服务器分布有多个:video.a.com file.a.com .看看域名就知道是一个公司,他想两边想互相去资源,结果不行了。那怎么办?凉拌呗。。。。
2.跨域处理的办法
好了,上面瞎说了比较多了,现在开始说说处理的办法吧。起始也是有的。首先可以从服务端着手处理,其次客户端也做处理。服务端这就是我们说的跨域处理Cors.客户端:主要在js上比如Jsonp、Iframe、等 。这是什么意思呢?简单一点就是,我从服务端如何处理跨域,我从客户端如何处理跨域。本次先将服务端的跨域问题,在下一节中我在说明一下客户端的解决办法。
3.webapi 如何处理跨域难题。(本章的重点)
重点来了,因为我这边只说明解决办法,没有整个项目的源码,所有说,我会先说明下方法,要靠各位先理解然后尝试。所谓吃的苦中苦方为人上人嘛,多折腾才会成长。
从我看到的文章来看主要是利用Cors来解决的,也就是说服务端需要加入一个Access-Control-Allow-Origin Response 头。来告诉服务器,我可以跨域请求哦。
1) 引用微软的WebApi.Cors 动态库文件,如何添加呢?右键项目名,点击“管理Nuget 程序包”-->“浏览”-->“搜索” 名称“输入关键字就可以了”WebApi.Cors“,选择第一个安装。
2)下面是准备两个web项目:1.客户端-->请求方(web),2.服务端-->应答方(webapi)
3) 修改代码:下面是三种处理办法,归结来说还是一种,只是程序处理地方不同而已。
添加引用:system.web.cors;system.web.http.cors;
3.1 在api 的webapiconfig.cs 添加程序:
public static void Register(HttpConfiguration config) { // Web API 配置和服务 // 跨域配置 //1. 只需要在这里添加该项即可 //config.EnableCors(new EnableCorsAttribute("*","*","*")); //2. 添加配置项 // 2.1在webconfig中添加配置项 // 2.2 在register中添加cors配置 #region register 配置 var allowedMethods = ConfigurationManager.AppSettings["cors:allowedMethods"].ToString(); var allowedOrigin = ConfigurationManager.AppSettings["cors:allowedOrigin"].ToString(); var allowedHeaders = ConfigurationManager.AppSettings["cors:allowedHeaders"].ToString(); var geduCors = new EnableCorsAttribute(allowedOrigin,allowedMethods, allowedHeaders) { SupportsCredentials = true }; config.EnableCors(geduCors); #endregion //3. 利用特性配置在某一个controller 或action上面。 // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); }
代码中注释的部分:
config.EnableCors(new EnableCorsAttribute("*","*","*"));
直接启动程序即可。
当然前提条件式,你的ui端有对这个webai 中某一个接口有ajax请求。
var ApiUrl = "http://localhost:8001/"; //服务端端口 $(function () { $.ajax({ type: "get", url: ApiUrl + "api/Charging/GetAllChargingData", data: {}, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } }, error: function (e) { $("#div_test").html("Error"); }, complete: function () { } }); });
启动项目时,要将项目设置成多项目程序启动,因为有了api服务后,你才可以请求呀,不然你到哪里去请求数据。就是说webapi 启动了,并且web去请求。
结果呢,成功了,对所有的域名。
3.2 这个其实是对第一个的改版而已。请请求需要的配置内容放到了webconfig中了。
这次利用途中为注释的部分2.
并在webconfig中添加对应配置项目。
<add key="cors:allowedMethods" value="*"/> <add key="cors:allowedOrigin" value="http://localhost:27239"/> <add key="cors:allowedHeaders" value="*"/>
代码中”http://localhost:27239"是说谁可以请求我的资源。
从代码中EnableCorsAttribute(string origin,string methods,string headers) ,一看就能明白,第一个参数表示:允许谁可以请求我(origin);第二个参数:请求的头文件:比如我们添加的头信息
第三个参数:请求的方式(getpostputdelete)四种比较常见的方式;
设置完毕后,运行程序,你会发现只有当请求web origin 是http://localhost:27239 才会成功返回数据,哪怕是多了一个’/‘都不可以的。
3.3 这种事简单的方式了。出去之前的所有配置,利用特性的方法:直接在Controller上面或者Action上面添加特性即可。
[EnableCors(origins: "http://localhost:27239", headers:"*",methods:"GET,POST,PUT,DELETE")] public class ChargingController : ApiController { [HttpGet] public string GetAllChargingData() { return "Success"; }
或者将attribute 添加到action 上面。
好了,好了从上面的三个方法中你看到了什么,发现其中都是调用的EnableCorsAttribute 特性,只不过是调用的时机不同而已了。
今天就先说到这里,有些地方会匆忙没能说明白的,我后期会慢慢补充。
同时很感觉博友的支持。附上作者链接如下:特别说明下,我只做知识的总结。
1. 跨域的解决办法
2. 跨域的详解