一、客户端用JSONP请求数据

如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持javascript的callback的,它返回的JSON是这样的:

  1. {"YourSignature": "给我钱"}

然而,JSONP请求期望得到这样的JSON:

  1. jQuery123456([{"YourSignature": "给我钱"}])

所以我们需要对WebAPI做拓展,让它支持这样的callback。我找到了两种办法。

1. 来自stackoverflow的方案:

http://stackoverflow.com/questions/9421312/jsonp-with-asp-net-web-api/18206518#18206518

自己写个Attribute,来给返回的JSON包上callback

  1. public class JsonCallbackAttribute : ActionFilterAttribute
  2. {
  3. private const string CallbackQueryParameter = "callback";
  4.  
  5. public override void OnActionExecuted(HttpActionExecutedContext context)
  6. {
  7. var callback = string.Empty;
  8.  
  9. if (IsJsonp(out callback))
  10. {
  11. var jsonBuilder = new StringBuilder(callback);
  12. jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result);
  13. context.Response.Content = new StringContent(jsonBuilder.ToString());
  14. }
  15. base.OnActionExecuted(context);
  16. }
  17.  
  18. private bool IsJsonp(out string callback)
  19. {
  20. callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter];
  21. return !string.IsNullOrEmpty(callback);
  22. }
  23. }

然后在要被调用的方法前加上这个Attribute:

  1. [JsonCallback]
  2. public IEnumerable<User> User()
  3. {
  4. return _user;
  5. }

非常简洁明了,但是这种方法有个缺点,就是被加了[JsonCallback]的方法,只能适用于JSONP的请求。如果你希望API能被各种场合的客户端调用,还是在服务端提供支持吧。

2. 通过自定义JsonMediaTypeFormatter实现

参见 Artech大神的文章: http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-03.html

二、服务端实现

方法一:支持CORS最地道的方法当然是在服务端提供支持,按官网的办法,100%成功。 http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

1. 到nuget上装一个包: http://www.nuget.org/packages/Microsoft.AspNet.WebApi.Cors/

2. 在WebApiConfig.Register方法中加入代码:

  1. config.EnableCors();

3. 在Controller上加上Attribute:

  1. [EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*", methods: "*")]

这个域名是可以配置的,具体还请参考上面给出的官网教程。

最后,还要告诉大家一个坑,在服务端完提供支持以后,不要高兴的太早,如果你用jQuery.ajax()的方式去请求,还是会爆的:

  1. $.ajax({
  2. url: 'yourCORSurl',
  3. data: '',
  4. dataType: 'json',
  5. type: 'GET',
  6. contentType: 'application/json; charset=utf-8',
  7. ...
  8. })

经过无数次爆破,终于发现,只要 把dataType和contentType两个参数去掉

方法二:配置 web.config

在  <system.webServer> 标签内添加以下代码

<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>

然而这里以为搞掂收工,谁知还有一个大坑

当你发送请求时,它居然把OPTIONS类型的请求给撸掉了!在jQuery等框架里发起CORS请求的时候,虽然你写的可能是“GET”,但是现在的浏览器是会自动把这个GET先撸成OPTIONS去访问服务的,这也叫“preflight”请求。如果你的服务拒绝OPTIONS这个verb,你会得到一个405的结果(用fiddler就可以看到)。

所以,要让WebAPI支持CORS,第一步就是在web.config里把“ <remove name="OPTIONSVerbHandler" /> ”删掉。

现在就可以正常访问了。

注意:

当使用方法一的时候,放在web Api的静态文件资源,比如图片,后台把图片路径传给前台后,前台通过jq想把图片转成base64 就发生跨域问题,

如果需要实现,只能采用第二种方法。

ASP.NET Web API 跨域访问(CORS)的更多相关文章

  1. ASP.NET Web API 跨域访问(CORS)要注意的地方

    一.客户端用JSONP请求数据 如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持javascript的callback的,它返回的JSON是这样的: {"YourSignatu ...

  2. ASP.NET Web API 跨域访问

    自定义特性 要在WebApi中实现JSONP,一种方式是实现自定义特性  http://stackoverflow.com/questions/9421312/jsonp-with-asp-net-w ...

  3. Web Api跨域访问配置及调用示例

    1.Web Api跨域访问配置. 在Web.config中的system.webServer内添加以下代码: <httpProtocol> <customHeaders> &l ...

  4. Web API 跨域访问(CORS)

    1.在web.config里把“    <remove name="OPTIONSVerbHandler" />  ”删掉. 2. 到nuget上装一个包:    ht ...

  5. asp.net web api 跨域问题

    缘起 以前在asp.net mvc时代,很少出现跨域问题 自从使用了asp.net web api + angular (1/2)之后,开始有跨域问题了. 简单普及下跨域: 我的理解是只要是前台页面与 ...

  6. asp.net web api 跨域,带cookie

    官网上有一个介绍 http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api 但是只支 ...

  7. ASP.NET web api 跨域请求

    1.学习文章:AJAX 跨域请求 - JSONP获取JSON数据 1.asp.net代码 参考文章:http://www.sxt.cn/info-2790-u-756.html (1).增加CorsH ...

  8. ASP.Net开发WebAPI跨域访问(CORS)的精简流程

    1: Web.config里有一行: <remove name="OPTIONSVerbHandler" /> 这个要删除. 2: nuget安装Microsoft.A ...

  9. web api 跨域访问

    在工程中 Install-Package Microsoft.AspNet.WebApi.Cors 在 webapiconfig.cs中 config.EnableCors(); 在 控制器中, [E ...

随机推荐

  1. Unity3d学习 制作地形

    这周学习了如何在unity中制作地形,就是在一个Terrain的对象上盖几座小山,在山底种几棵树,那就讲一下如何完成上述内容. 1.在新键得项目的游戏的Hierarchy目录中新键一个Terrain对 ...

  2. MySQL高级知识- MySQL的架构介绍

    [TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ...

  3. 漫扯:从polling到Websocket

    Http被设计成了一个单向的通信的协议,即客户端发起一个request,然后服务器回应一个response.这让服务器很为恼火:我特么才是老大,我居然不能给小弟发消息... 轮询 老大发火了,小弟们自 ...

  4. CSS Position 定位属性

    本篇文章主要介绍元素的Position属性,此属性可以设置元素在页面的定位方式. 目录 1. 介绍 position:介绍position的值以及辅助属性. 2. position 定位方式:介绍po ...

  5. Unity 序列化

    Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs ...

  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(81)-数据筛选(万能查询)

    系列目录 前言 听标题的名字似乎是一个非常牛X复杂的功能,但是实际上它确实是非常复杂的,我们本节将演示如何实现对数据,进行组合查询(数据筛选) 我们都知道Excel中是如何筛选数据的.就像下面一样 他 ...

  7. 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包

            微信支付教程系列之现金红包           最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...

  8. mysql进阶之存储过程

    往往看别人的代码会有这样的感慨: 看不懂 理还乱 是离愁 别是一番滋味在心头 为什么要使用存储过程? 在mysql开发中使用存储过程的理由: 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定 ...

  9. 快递Api接口 & 微信公众号开发流程

    之前的文章,已经分析过快递Api接口可能被使用的需求及场景:今天呢,简单给大家介绍一下微信公众号中怎么来使用快递Api接口,来完成我们的需求和业务场景. 开发语言:Nodejs,其中用到了Neo4j图 ...

  10. 深入浅出Redis-redis哨兵集群

    1.Sentinel 哨兵 Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所 ...