通过微软的cors类库,让ASP.NET Web API 支持 CORS

前言:因为公司项目需要搭建一个Web API 的后端,用来传输一些数据以及文件,之前有听过Web API的相关说明,但是真正实现的时候,感觉还是需要挺多知识的,正好今天有空,整理一下这周关于解决CORS的问题,让自己理一理相关的知识。

ASP.NET Web API支持CORS方式,据我目前在网上搜索,有两种方式

  • 通过扩展CorsMessageHandle实现:             http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-04.html
  • 通过微软的 AspNet.WebApi.Cors 类库实现  http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#intro

本文主要是利用AspNet.WebApi.Cors 类库实现CORS,因为在选择的过程中,发现扩展的CorsMessageHandle会有一些限制,因为真正项目的HTTP Request 是Rang Request.

你需要了解的一些知识

  • Web API 2.0              http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
  • 同源策略与JSONP     http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-01.html
  • CORS                         http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-02.html

1.创建Web API (myservice.azurewebsites.net)

这个简单放上图:

1.1

通过微软的cors类库,让ASP.NET Web API 支持 CORS

1.2

通过微软的cors类库,让ASP.NET Web API 支持 CORS

1.3

通过微软的cors类库,让ASP.NET Web API 支持 CORS

1.4

通过微软的cors类库,让ASP.NET Web API 支持 CORS

1.5

通过微软的cors类库,让ASP.NET Web API 支持 CORS

1.6将下面的code替代原来的TestController

using System.Net.Http;using System.Web.Http;namespace WebService.Controllers{    public class TestController : ApiController    {        public HttpResponseMessage Get()        {            return new HttpResponseMessage()            {                Content = new StringContent("GET: Test message")            };        }        public HttpResponseMessage Post()        {            return new HttpResponseMessage()            {                Content = new StringContent("POST: Test message")            };        }        public HttpResponseMessage Put()        {            return new HttpResponseMessage()            {                Content = new StringContent("PUT: Test message")            };        }    }}

1.7 可以测试创建的Web API是否可以正常工作

2.创建Client端(myclilent.azurewebsites.net)

这也是可以简单上图:

2.1

通过微软的cors类库,让ASP.NET Web API 支持 CORS

2.2

通过微软的cors类库,让ASP.NET Web API 支持 CORS

2.3 找到 Client端的 Views/Home/Index.cshtml,用下面代码替代

<div>    <select id="method">        <option value="get">GET</option>        <option value="post">POST</option>        <option value="put">PUT</option>    </select>    <input type="button" value="Try it" onclick="sendRequest()" />    <span id='value1'>(Result)</span></div>@section scripts {<script>    var serviceUrl = 'http://myservice.azurewebsites.net/api/test'; // Replace with your URI.    function sendRequest() {        var method = $('#method').val();        $.ajax({            type: method,            url: serviceUrl        }).done(function (data) {            $('#value1').text(data);        }).error(function (jqXHR, textStatus, errorThrown) {            $('#value1').text(jqXHR.responseText || textStatus);        });    }</script>}

2.4用例外一个域名发布网站,然后进入Index 页面,选择 GET,POST,PUT 等,点击 Try it 按钮,就会发送请求到Web API, 因为Web API没有开启CORS,而通过AJAX请求,浏览器会提示 错误

通过微软的cors类库,让ASP.NET Web API 支持 CORS

3.Web API支持CORS

3.1打开VS,工具->库程序包管理器->程序包管理器控制台 ,输入下列命令:Install-Package Microsoft.AspNet.WebApi.Cors -Version 5.0.0  

注意 :目前Nuget 上面最新的版本是5.2.0 ,但是我测试,下载的时候,会有一些关联的类库不是最新的,System.Net.Http.Formatting 要求是5.2,我在网上找不带这dll,因此建议安装 :Microsoft.AspNet.WebApi.Cors 5.0就OK了。

Nuget 科普link:    http://www.cnblogs.com/dubing/p/3630434.html

通过微软的cors类库,让ASP.NET Web API 支持 CORS

3.2 打开 WebApiConfig.Register 添加 config.EnableCors()

using System.Web.Http;namespace WebService{    public static class WebApiConfig    {        public static void Register(HttpConfiguration config)        {            // New code            config.EnableCors();            config.Routes.MapHttpRoute(                name: "DefaultApi",                routeTemplate: "api/{controller}/{id}",                defaults: new { id = RouteParameter.Optional }            );        }    }}

3.3 添加[EnableCors] 特性 到 TestController

using System.Net.Http;using System.Web.Http;using System.Web.Http.Cors;namespace WebService.Controllers{    [EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*", methods: "*")]    public class TestController : ApiController    {        // Controller methods not shown...    }}

3.4回到Client端,这时再次发送请求,会提示成功信息,证明CORS已经实现了。

通过微软的cors类库,让ASP.NET Web API 支持 CORS

4.为[EnableCors]设置到 Action, Controller, Globally

4.1Action

public class ItemsController : ApiController{    public HttpResponseMessage GetAll() { ... }    [EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]    public HttpResponseMessage GetItem(int id) { ... }    public HttpResponseMessage Post() { ... }    public HttpResponseMessage PutItem(int id) { ... }}

4.2Controller

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]public class ItemsController : ApiController{    public HttpResponseMessage GetAll() { ... }    public HttpResponseMessage GetItem(int id) { ... }    public HttpResponseMessage Post() { ... }    [DisableCors]    public HttpResponseMessage PutItem(int id) { ... }}

4.3Globally

public static class WebApiConfig{    public static void Register(HttpConfiguration config)    {        var cors = new EnableCorsAttribute("www.example.com", "*", "*");        config.EnableCors(cors);        // ...    }}

5.[EnableCors]工作原理

要理解CORS成功的原理,我们可以来查看一下

跨域的请求

GET http://myservice.azurewebsites.net/api/test HTTP/1.1Referer: http://myclient.azurewebsites.net/Accept: */*Accept-Language: en-USOrigin: http://myclient.azurewebsites.netAccept-Encoding: gzip, deflateUser-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)Host: myservice.azurewebsites.net

当发送请求的时候,浏览器会将“Origin”的请求头发送给 服务端,如果服务端允许跨域请求,那么响应回来的请求头,添加“Access-Control-Allow-Origin”,以及将请求过来的 域名 的value添加到 Access-Control-Allow-Origin,浏览器接收到这个 请求头,则会显示返回的数据,否则,即使服务端成功返回数据,浏览器也不会接收

服务器的响应

HTTP/1.1 200 OKCache-Control: no-cachePragma: no-cacheContent-Type: text/plain; charset=utf-8Access-Control-Allow-Origin: http://myclient.azurewebsites.netDate: Wed, 05 Jun 2013 06:27:30 GMTContent-Length: 17GET: Test message

6.自定义CORS Policy Providers

6.1除了使用自带的[EnableCors]特性外,我们可以自定义自己的[EnableCors]。首先是要继承Attribute 和 ICorsPolicyProvider 接口

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider {    private CorsPolicy _policy;    public MyCorsPolicyAttribute()    {        // Create a CORS policy.        _policy = new CorsPolicy        {            AllowAnyMethod = true,            AllowAnyHeader = true        };        // Add allowed origins.        _policy.Origins.Add("http://myclient.azurewebsites.net");        _policy.Origins.Add("http://www.contoso.com");    }    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)    {        return Task.FromResult(_policy);    }}

实现后,可以添加自己定义的[MyCorsPolicy]

[MyCorsPolicy]public class TestController : ApiController{    .. //

6.2或者你也可以从配置文件中读取 允许的域名

public class CorsPolicyFactory : ICorsPolicyProviderFactory{    ICorsPolicyProvider _provider = new MyCorsPolicyProvider();    public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)    {        return _provider;    }} public static class WebApiConfig{    public static void Register(HttpConfiguration config)    {        config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());        config.EnableCors();        // ...    }}
 
 http://www.th7.cn/Program/net/201407/234213.shtml
上一篇:[翻译]在ASP.NET Web API中通过OData支持查询和分页


下一篇:TCP服务器不回复SYN的问题