標籤:des style blog http color os 使用 io strong
WepApi確實方便好用,沒有設定檔,一個apicontroller直接可以幹活了。但今天用$.ajax跨域請求的時候總是擷取不到資料,用fiddler一看確實抓到了資料,但回到$.ajax函數中,直接觸發了error,沒有觸發success,即使狀態代碼是200。用apiclient或者瀏覽器直接存取都是ok的。搜羅一番。最終在這篇文章上面找到答案 。http://code.msdn.microsoft.com/windowsdesktop/Implementing-CORS-support-a677ab5d
原因
在預設情況下,為防止CSRF跨站偽造攻擊,一個網頁從另外一個域的網頁擷取資料的時候就會受到限制。有一些方法可以突破這個限制,JSONP就是其一。它使用<script> 標籤加一個回呼函數。但JSONP 只支援Get方法。而CORS(Cross-Origin Resource Sharing) 跨域資源共用,是一種新的header規範,可以讓伺服器端放鬆跨域的限制,可以根據header來切換限制或不限制跨域請求。它支援所有的Http請求方式。跨域的資源請求帶有一個Http header:Origin,如果伺服器支援CORS,響應就會帶有一個header:Access-Control-Allow-Origin ,也有一些特殊的請求。採用 HTTP “OPTIONS” 的方式,hearder中帶有Access-Control-Request-Method或Access-Control-Request-Headers,伺服器響應的hearder中需要帶有Access-Control-Allow-Methods,Access-Control-Allow-Headers才行。
實現
那怎麼實現CORS呢,這用到了Message Handler。它可以在管道中攔截並修改Request,代碼如下:
public class CorsHandler : DelegatingHandler { const string Origin = "Origin"; const string AccessControlRequestMethod = "Access-Control-Request-Method"; const string AccessControlRequestHeaders = "Access-Control-Request-Headers"; const string AccessControlAllowOrigin = "Access-Control-Allow-Origin"; const string AccessControlAllowMethods = "Access-Control-Allow-Methods"; const string AccessControlAllowHeaders = "Access-Control-Allow-Headers"; protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { bool isCorsRequest = request.Headers.Contains(Origin); bool isPreflightRequest = request.Method == HttpMethod.Options; if (isCorsRequest) { if (isPreflightRequest) { return Task.Factory.StartNew<HttpResponseMessage>(() => { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First()); string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault(); if (accessControlRequestMethod != null) { response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod); } string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders)); if (!string.IsNullOrEmpty(requestedHeaders)) { response.Headers.Add(AccessControlAllowHeaders, requestedHeaders); } return response; }, cancellationToken); } else { return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t => { HttpResponseMessage resp = t.Result; resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First()); return resp; }); } } else { return base.SendAsync(request, cancellationToken); } } }
然後在Global中加入:
protected void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler()); WebApiConfig.Register(GlobalConfiguration.Configuration); }
指令碼:
$.ajax({ // url: "http://localhost:11576/api/Values", url: "http://localhost:39959/api/user/login?name=niqiu&pwd=123456", type: "GET", //contentType: "application/json;", success: function(result) { alert(result.status); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert("出錯!XMLHttpRequest:" + XMLHttpRequest.status); } });
這樣訪問就ok了。
$.ajax 跨域請求 Web Api