zoukankan      html  css  js  c++  java
  • ASP.NET Web API 跨域访问(CORS)

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

    前几天我在帮队友撸一个WebAPI的跨域访问问题,被爆出了翔,今天正好有时间总结一下经验。

    首先一个最坑之坑,也是ASP.NET官网上都没有提到的坑,是Web.config里的配置。大家看这个建立WebAPI项目之后,默认的Web.config:

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

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

    接下来,要实现CORS,有两种办法。一是在客户端完成(要求对WebAPI做少量拓展),二是在服务端(WebAPI)本身做支持。

    一、客户端用JSONP请求数据

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

    {"YourSignature": "嫁人要嫁程序员,钱多话少死得早"}

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

    jQuery123456([{"YourSignature": "嫁人要嫁程序员,钱多话少死得早"}])

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

    1. 我个人比较喜欢的是来自stackoverflow的方案:

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

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

    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());
            }
            base.OnActionExecuted(context);
        }
    
        private bool IsJsonp(out string callback)
        {
            callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter];
            return !string.IsNullOrEmpty(callback);
        }
    }

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

    [JsonCallback]
    public IEnumerable<User> User()
    {
        return _user;
    }

    非常简洁明了,但是这种方法有个缺点,就是被加了[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方法中加入代码:

    config.EnableCors();

    3. 在Controller上加上Attribute:

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

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

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

    $.ajax({
        url: 'yourCORSurl',
        data: '',
        dataType: 'json',
        type: 'GET',
        contentType: 'application/json; charset=utf-8',
        ...
    })

    经过无数次爆破,终于发现,只要把dataType和contentType两个参数去掉,就肯定不会爆了!!!虽然不知道为什么,但代码能用了,码农就能按时回家了:)

    http://diaosbook.com/Category/List/MVC

  • 相关阅读:
    python一些简单操作
    MySQL事务
    c#替换word中的文本并导出(示例)
    SQLServer将某个字段的多行记录合并返回一行
    SQL根据某字段查询不重复记录
    SQLServer逗号分割字符串返回多行
    c# js日期工具
    onchange,onfocus ,oninput事件
    compositionstart事件与compositionend事件
    图片处理问题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4211647.html
Copyright © 2011-2022 走看看