WebApi跨域的解决方法

      由于前段时间项目需求,需要用到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
原文地址:https://www.cnblogs.com/kingleo/p/8493329.html