• WebAPI的跨域访问CORS三种方法


    跨域访问:

    JSONP的原理利用<script>没有跨域访问的限制,利用<script>的src跨域访问api,api会根据数据把json包装在一个js里面,这样跨域的客户端拿到json的包装(json padding)就会调用本地的函数解析数据。总结来说就是利用两点1、浏览器的跨域限制其实是接收了数据,但限制使用跨域数据。2是利用script标签可以跨域回调的功能

    1、JSONP——js

    api服务端

    public HttpResponseMessage GetAllContacts(string callback)
            {
                Contact[] contacts = new Contact[]
                {
                    new Contact{ Name="张三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},
                    new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},
                    new Contact{ Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"},
                };
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                string content = string.Format("{0}({1})", callback, serializer.Serialize(contacts));
                return new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(content, Encoding.UTF8, "text/javascript")
                };
            }
    View Code

    客户端

    <head>
        <title>联系人列表</title>
        <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>
        <script type="text/javascript">
            function listContacts(contacts)
            {
                $.each(contacts, function (index, contact) {
                    var html = "<li><ul>";
                    html += "<li>Name: " + contact.Name + "</li>";
                    html += "<li>Phone No:" + contact.PhoneNo + "</li>";
                    html += "<li>Email Address: " + contact.EmailAddress + "</li>";
                    html += "</ul>";
                    $("#contacts").append($(html));
                });
            }
        </script>
    </head>
    <body>
        <ul id="contacts"></ul>
        <script type="text/javascript" src="http://localhost:3721/api/contacts?callback=listContacts"></script>
    </body>
    </html>
    View Code

    2、JSONP——JsonMediaTypeFormatter

    服务端定义类:

        public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
        {
            public string Callback { get; private set; }
            public JsonpMediaTypeFormatter(string callback = null)
            {
                this.Callback = callback;
            }
            public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
            {
                if (string.IsNullOrEmpty(this.Callback))
                {
                    return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
                }
                try
                {
                    this.WriteToStream(type, value, writeStream, content);
                    return Task.FromResult<AsyncVoid>(new AsyncVoid());
                }
                catch (Exception exception)
                {
                    TaskCompletionSource<AsyncVoid> source = new TaskCompletionSource<AsyncVoid>();
                    source.SetException(exception);
                    return source.Task;
                }
            }
    
            private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
            {
                JsonSerializer serializer = JsonSerializer.Create(this.SerializerSettings);
                using (StreamWriter streamWriter = new StreamWriter(writeStream, this.SupportedEncodings.First()))
                using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter) { CloseOutput = false })
                {
                    jsonTextWriter.WriteRaw(this.Callback + "(");
                    serializer.Serialize(jsonTextWriter, value);
                    jsonTextWriter.WriteRaw(")");
                }
            }
    
            public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
            {
                if (request.Method != HttpMethod.Get)
                {
                    return this;
                }
                string callback;
                if (request.GetQueryNameValuePairs().ToDictionary(pair => pair.Key, pair => pair.Value).TryGetValue("callback", out callback))
                {
                    return new JsonpMediaTypeFormatter(callback);
                }
                return this;
            }
    
            [StructLayout(LayoutKind.Sequential, Size = 1)]
            private struct AsyncVoid{ }
        }
    View Code

    注册到Global中

    GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter());

    直接返回数据让系统自动协商优先使用

    客户端:

    $(function ()
            {
                $.ajax({
                    type: "GET",
                    url: "http://localhost:3721/api/contacts",
                    dataType: "jsonp",
                    success: listContacts
                });
            });
    
            function listContacts(contacts) {
                $.each(contacts, function (index, contact) {
                    var html = "<li><ul>";
                    html += "<li>Name: " + contact.Name + "</li>";
                    html += "<li>Phone No:" + contact.PhoneNo + "</li>";
                    html += "<li>Email Address: " + contact.EmailAddress
                            + "</li>";
                    html += "</ul>";
                    $("#contacts").append($(html));
                });
            }
    View Code

    3、Microsoft AsRNET Web API2Cross-Origin support

    原理:利用http的响应包标识Header;Access-Control-Allow-Origin等等标签标识允许跨域访问

    Install-Package Microsoft.AspNet.WebApi.Cors

    开启方法:

    GlobalConfiguration.Configuration.EnableCors();

    或在webapiconfig注册路由里开启

    config.EnableCors(); 

    api使用特性:

    [EnableCors("http://localhost:9527","*","*")]

    做全局配置Global/WebApiConfig:

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

    也可以只针对Controller或者Action做配置

    [EnableCors(origins: "http://www.ClientA.com", headers: "*", methods: "*")]
    public class ItemsController : ApiController
    {
        public HttpResponseMessage GetAll() { ... }
        [EnableCors(origins: "http://www.ClientB.com", headers: "*", methods: "*")]
        public HttpResponseMessage GetItem(int id) { ... }
        public HttpResponseMessage Post() { ... }
     
        [DisableCors]
        public HttpResponseMessage PutItem(int id) { ... }
    }
  • 相关阅读:
    职业生涯起步不要去顶级公司
    discuz uc密码修改
    习惯决定成功与否
    世上没有理想的工作
    中山市慧海人力资源服务有限公司
    Codeforces Round #365 (Div. 2) B 前缀和
    Codeforces Round #365 (Div. 2) A 水
    tyvj 1067 dp 两次LIS(nlogn)
    Codeforces Round #303 (Div. 2) D 贪心
    Codeforces Round #303 (Div. 2) C dp 贪心
  • 原文地址:https://www.cnblogs.com/xmai/p/6514002.html
Copyright © 2020-2023  润新知