由于前段时间项目需求,需要用到WebApi跨域,我在网上也查阅很多这方面的资料,但是最终还是决定自己写一篇记录一下。
当一个请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
先说明一下出现跨域的原因:
同源策略:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容。
关于这方面的说明网上有很多,这里只是大概说明一下。
我在这里解决这个问题的方法是使用CORS(Cross-Origin Resource Sharing 跨源资源共享):
首先,新建一个MVC项目和WebApi项目,如图:
接着在WebApiCors项目的Models中添加一个类Product
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebApi.Models { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } }
然后添加一个Controller,如下图:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using WebApi.Models; namespace WebApi.Controllers { public class ProductController : ApiController { private static IList<Product> products = new List<Product> { new Product() { Id=1, Name = "苹果", Category = "水果", Price = 3 }, new Product() { Id=2, Name = "茄子", Category = "蔬菜", Price = 2 }, new Product() { Id=3, Name = "牛排", Category = "肉类", Price = 30 } }; public IEnumerable<Product> GetAll() { return products; } public Product GetProductById(int id) { return products.FirstOrDefault(x => x.Id == id); } } }
接下来在Web项目中添加一个Controller:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Web.Controllers { public class ProductController : Controller { // // GET: /Product/ public ActionResult Index() { return View(); } } }
添加一个view,用于展示请求的数据:
@{ ViewBag.Title = "Index"; } <!DOCTYPE html> <html> <head> <title></title> <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script type="text/javascript"> jQuery.support.cors = true; $(function () { $.ajax({ type: 'get', async: false, url: 'http://localhost:43450/api/Product', data: {}, success: function (result) { var json = result; for (var i = 0; i < json.length; i++) { $("#products").append("<tr><td>" + (parseInt(i) + 1) + "</td><td>" + json[i].Name + "</td><td>" + json[i].Category + "</td><td>" + json[i].Price + "</td></tr>"); } } }); }); </script> </head> <body> <table id="products" cellspacing=0 cellpadding=0 border=1> <thead> <tr> <th>序号</th> <th>名称</th> <th>分类</th> <th>价格(元)</th> </tr> </thead> </table> </body> </html>
另外,补充一下:要是项目中需要只输出json格式的数据可以在Global.asax文件中添加语句
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
如下图
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace WebApiCors { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); //设置以JSON 格式返回数据 GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); } } }
做好上面的准备工作下面就可以开始请求数据。
由于我这两个项目的端口号并不一致,要是按照正常情况访问的话就会出现跨域问题,如下图:
这是因为受到了同源策略的约束,因此不能直接访问接口,下面通过Nuget搜索到CORS安装,如图
安装好之后,在WebApi项目中配置,在App_Start文件夹中找到WebApiConfig.cs文件,添加语句:
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
如下图:
EnableCorsAttribute的构造函数指定的三个参数均为*,表示支持所有的访问。
第一个参数表示访问的源;第二个参数表示访问的头信息;第三个参数表示允许的方法,比如:HEAD、OPTIONS、DELETE、GET、POST等等。
配置好之后再次请求,结果如下图:
可以看到之前出现的跨域限制的问题已经没了。
总结一下:上面只是做了一个简单的CORS解决跨域的实例,还不够深入,由于技术有限,还是要慢慢研究,另外看到网上有关IE8,IE9部分支持跨域问题,这个也有待研究。
参考文章:https://docs.microsoft.com/en-us/aspnet/web-api/overview/releases/whats-new-in-aspnet-web-api-21
参考文章:https://www.cnblogs.com/landeanfen/p/5177176.html