【转】web api 跨域请求,ajax跨域调用webapi

No 'Access-Control-Allow-Origin' header is present on the requested resource

在写手机网站时,要访问非同源的webapi读取json数据,结果碰到上述错误。从网上找了不少资料,最后弄明白了是ajax跨域问题,所以就把比较好的一篇文章转帖过来,希望能帮助更多的小朋友。下面是转发内容:

---------------------------------------------------------------------------------

1、跨域问题仅仅发生在Javascript发起AJAX调用,或者Silverlight发起服务调用时,其根本原因是因为浏览器对于这两种请求,所给予的权限是较低的,通常只允许调用本域中的资源,除非目标服务器明确地告知它允许跨域调用。假设我们页面或者应用已在 http://www.test1.com 上了,而我们打算从 http://www.test2.com 请求提取数据。一般情况下,如果我们直接使用 AJAX 来请求将会失败,浏览器也会返回“源不匹配”的错误,"跨域"也就以此由来。

2、什么是跨域呢?

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。通常来说,跨域分为以下几类:

在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

 

3、当发起AJAX跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况。

出现如下错误信息

在这里跟大家解释一下 Access-Control-Allow-Origin是HTML5中定义的一种服务器端返回Response header,用来解决资源(比如字体)的跨域权限问题。

当Access-Control-Allow-Origin后面跟URL 或 *,如果是 URL 则只会允许来自该 URL 的请求,* 则允许任何域的请求

例如:header('Access-Control-Allow-Origin:http://A.abc.com')||header('Access-Control-Allow-Origin:*')

意思是说只有当你请求的资源被允许跨域的时候才可以被访问。

那么我们该怎么设置Access-Control-Allow-Origin呢?

 

4、第一种是用JSONP来获得跨域的数据,而WebAPI本身是不支持javascript的callback的

 比较一下json与jsonp格式的区别:

json格式:

{
    "message":"获取成功",
    "state":"1",
    "result":{"name":"工作组1","id":1,"description":"11"}
}

jsonp格式:

callback({
    "message":"获取成功",
    "state":"1",
    "result":{"name":"工作组1","id":1,"description":"11"}
})

看出来区别了吧,在url中callback传到后台的参数是神马callback就是神马,jsonp比json外面有多了一层,callback()。

只需要给全局注册一个JsonCallbackAttribute,就可以判断接口的访问是属于跨域,还是非跨域,正常的返回。

因为我们的接口,可能是用来给 移动端(Android 、IOS)做数据接口,也有可能是给网站用,所以,考虑到可能存在跨域的问题。

   GlobalConfiguration.Configuration.Filters.Add(new JsonCallbackAttribute());

复制代码

复制代码

 public class JsonCallbackAttribute : ActionFilterAttribute
    {
        private const string CallbackQueryParameter = "callback";

        public override void OnActionExecuted(HttpActionExecutedContext context)
        {
            var callback = string.Empty;

            if (IsJsonp(out callback))
            {
                var jsonBuilder = new StringBuilder(callback);

                jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result);

                context.Response.Content = new StringContent(jsonBuilder.ToString());
                //context.Response.Content = new StringContent("C(\"a\")");
            }

            base.OnActionExecuted(context);
        }

        private bool IsJsonp(out string callback)
        {
            callback = System.Web.HttpContext.Current.Request.QueryString[CallbackQueryParameter];

            return !string.IsNullOrEmpty(callback);
        }

复制代码

复制代码

结合下面图片不难开出,请求的地址带回了,callback的参数标识。

当然也可以用解决跨域问题的jQuery插件-jquery-jsonp,有第一种方式的基础,使用jsonp插件也就比较简单了,server端代码无需任何改动。

5、服务端直接修改配置文件,个人认为这种方式好一点,毕竟我们所写的api是对外公开的,安全访问的控制还是要通过其他方法来保证。

针对ASP.NET MVC,只需要在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>

<handlers>

<remove name="ExtensionlessUrlHandler-Integrated-4.0" />

<remove name="OPTIONSVerbHandler" />

<remove name="TRACEVerbHandler" />

<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

</handlers>

</system.webServer>

  

针对ASP.NET Web API,除了上面这样的设置,还需要添加一个特殊的设计,就是为每个APIController添加一个OPTIONS的方法,但无需返回任何东西。

public string Options()

{

return null; // HTTP 200 response with empty body

}

6、还有用CORS(跨域资源共享,Cross-Origin Resource Sharing)来解决的, CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

hander() 设置,“*”号表示允许任何域向我们的服务端提交请求

     

  也可以设置指定的域名,如域名 http://www.test2.com ,那么就允许来自这个域名的请求

     

这种没有仔细研究,其实跟上面的配置文件,差不多,都是去设置响应头。

 

本文是结合好多其他作者的文章:

http://www.cnblogs.com/chenxizhang/p/3821703.html

http://www.cnblogs.com/sunxucool/p/3433992.html

http://www.cnblogs.com/Darren_code/p/cors.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值