目前的項目是前端mv*+api的方式進行開發的,之前都是沒有跨域的方案,先後端人員在同一個解決方案裏邊進行開發,前端人員要用IIS或VS來開發和調試Api,這樣就很不方便,迫切須要跨域訪問Api.javascript
評選了不少解決方案最終選擇,CORS+WebApicss
cors科普:http://www.ruanyifeng.com/blog/2016/04/cors.htmlhtml
cors網站:http://enable-cors.org/前端
mvc源碼:https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http.Cors/CorsMessageHandler.csjava
快速入門能夠看一些教程,本身要擴展源碼是一條捷徑.jquery
示例代碼:https://github.com/gutun/aspnet/tree/master/corsgit
1.新建WebApi項目實現CORS跨域github
1.1 新建一個新的項目CrossDomainweb
1.2. 安裝 Microsoft.AspNet.WebApi.Corsajax
Install-Package Microsoft.AspNet.WebApi.Cors
1.3. 配置App_Start目錄下的 WebApiConfig文件
Config中要啓用 CORS的支持我選擇默認的MediaType爲json方式。
1.4 新增UserController,在裏邊新增兩個方法,get用來ping,表明url是通的,post模擬真正的數據提交,咱們全部的api訪問走post, request的入參和出參能夠定義通用的實體。這裏模擬post提交數據解析成UserInfo的實例。
2.JQuery Ajax跨域
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script> </head> <body> <script> $.ajax({ url:'http://localhost:64542/api/user', type:'POST', data:{"Id":"1","Name":"張三"}, dataType:'json', //Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain //contentType: 'application/json; charset=utf-8', cache: false, crossDomain: true, success:function(data){ alert(data); } }); </script> </body> </html>
使用Nodejs本地服務器訪問WebApi項目,成功的訪問到了api/User,狀態是200.
3.IE8,IE9支持CORS.
CORS在瀏覽器的支持狀況,IE8和IE9是部分兼容,86%的瀏覽器是支持的,佔了大部分,爲了支持IE8和IE9我找到了一個補丁jquery.transport.xdr.min.js 用來彌補在IE8和IE9下的不足。
https://github.com/gfdev/javascript-jquery-transport-xdr.js
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script> <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script> <!--[if (IE 8)|(IE 9)]> <script src="http://cdn.rawgit.com/gfdev/javascript-jquery-transport-xdr/master/dist/jquery.transport.xdr.min.js"></script> <![endif]--> </head> <body> <script> //http://www.ruanyifeng.com/blog/2016/04/cors.html $.ajax({ url:'http://localhost:64542/api/user', type:'POST', data:{"Id":"1","Name":"張三"}, dataType:'json', //Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain //contentType: 'application/json; charset=utf-8', cache: false, crossDomain: true, success:function(data){ alert(data); } }); </script> </body> </html>
喜出往外,跑起來後遇到了,415錯誤,未識別的Content-Type,這是由於在IE8和IE9下,Content-Type爲空形成的。
http://stackoverflow.com/questions/18964258/asp-web-api-post-request-with-cors-and-ie9-xdomainrequest-objec
新增DefaultContentTypeMessageHandler用來處理Request
using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Web.Cors; using System.Web.Http.Cors; namespace CrossDomain { public class DefaultContentTypeMessageHandler : DelegatingHandler { protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { CorsRequestContext corsRequestContext = request.GetCorsRequestContext(); if (corsRequestContext != null) //判斷是不是跨域的請求 { if (request.Method == HttpMethod.Post && request.Content.Headers.ContentType == null) //ConentType爲空,使用默認值 request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded"); } var response = await base.SendAsync(request, cancellationToken); return response; } } }
再次更改WebApiConfig文件,在MessageHandlers管道中追加剛寫的DefaultContentTypeMessageHandler,這樣ContentType爲空的跨域請求會使用默認的ContentType.
using System.Web.Http; using System.Web.Http.Cors; namespace CrossDomain { public static class WebApiConfig { public static void Register(HttpConfiguration config) { //新增CORS支持 var corsAttr = new EnableCorsAttribute("*", "*", "*"); config.EnableCors(corsAttr); //默認使用json格式,移除xml格式 config.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); //處理Content-Type config.MessageHandlers.Add(new DefaultContentTypeMessageHandler()); // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
在chrome,IE8,IE9,IE10+上測試沒有問題。