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) { ... }
}
原文地址:https://www.cnblogs.com/xmai/p/6514002.html