最近ajax訪問webservice遇到跨域的問題,網上搜索資料,總結以下(不少都是以爲人家總結不錯的複製下來)javascript
<<用JSON來傳數據,靠JSONP來跨域>>html
先上個人已實現代碼:前端
前端代碼:java
$.ajax({jquery
type: "get",web
url: "http://localhost/Service1.asmx/getElevatorStatusJsonData?jsoncallback=?",ajax
dataType: "jsonp",chrome
jsonp: "json",json
data: "",c#
success: function (result) {
var data = eval(result);
for (var i = 0; i < data.length; i++) {
alert(data[i].ID + "--" + data[i].Name);
}
},
error: function (a, b, c) {
alert(c);
}
});
服務端代碼:
c#
/// <summary>
/// 獲取狀態數據信息
/// </summary>
/// <returns></returns>
[WebMethod]
public void getElevatorStatusJsonData()
{
List<List<DeviceInfo>> elevatordatas = new List<List<DeviceInfo>>();
List<SendDicdate> searchList = XmlSerializeHelper.XmlDeserializeFromFile<List<SendDicdate>>(@ConfigUtil.servicePath + ConfigUtil.getConfigByKey("xmlPath") + "查詢指令信息.xml", Encoding.UTF8);
foreach (SendDicdate item in searchList)
{
string key = item.portno + "-" + item.bordrate + "-" + item.sendtype;
List<DeviceInfo> deviceInfoList = (List<DeviceInfo>)Context.Cache.Get(key);
elevatordatas.Add(deviceInfoList);
}
String result = "";
DataContractJsonSerializer json = new DataContractJsonSerializer(elevatordatas.GetType());
using (MemoryStream stream = new MemoryStream())
{
json.WriteObject(stream, elevatordatas);
result = Encoding.UTF8.GetString(stream.ToArray());
}
String jsoncallback = HttpContext.Current.Request["jsoncallback"];
result = jsoncallback + '(' + result + ')';
HttpContext.Current.Response.Write(result);
HttpContext.Current.Response.End();
}
以上是調用c#服務端的實現代碼,下面的是java端的,參數可能有差別,但原理是相通的
java:
String callbackFunName = context.Request["callbackparam"];
context.Response.Write(callbackFunName + "([ { \"name\":\"John\"}])");
PS:客戶端的jsonp參數是用來經過url傳參,傳遞jsonpCallback參數的參數名,比較拗口,通俗點講:
jsonp: "" jsonpCallback:""
順帶一提:
在chrome瀏覽器裏,還能夠在服務端設置header信息
context.Response.AddHeader("Access-Control-Allow-Origin", "*");
來達到跨域請求的目的,而且不須要設置ajax如下參數
dataType : "jsonp", jsonp: "callbackparam", jsonpCallback:"jsonpCallback1"
以正常ajax請求方式就能夠得到數據。
下面是原理,看別人講解的,感受頗有道理:
一、一個衆所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一概不許;
二、不過咱們又發現,Web頁面上調用js文件時則不受是否跨域的影響(不只如此,咱們還發現凡是擁有」src」這個屬性的標籤都擁有跨域的能力,好比<script>、<img>、<iframe>);
三、因而能夠判斷,當前階段若是想經過純web端(ActiveX控件、服務端代理、屬於將來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件裏,供客戶端調用和進一步處理;
四、恰巧咱們已經知道有一種叫作JSON的純字符數據格式能夠簡潔的描述複雜數據,更妙的是JSON還被js原生支持,因此在客戶端幾乎能夠爲所欲爲的處理這種格式的數據;
五、這樣子解決方案就呼之欲出了,web客戶端經過與調用腳本如出一轍的方式,來調用跨域服務器上動態生成的js格式文件(通常以JSON爲後綴),顯而易見,服務器之因此要動態生成JSON文件,目的就在於把客戶端須要的數據裝入進去。
六、客戶端在對JSON文件調用成功以後,也就得到了本身所需的數據,剩下的就是按照本身需求進行處理和展示了,這種獲取遠程數據的方式看起來很是像AJAX,但其實並不同。
七、爲了便於客戶端使用數據,逐漸造成了一種非正式傳輸協議,人們把它稱做JSONP,該協議的一個要點就是容許用戶傳遞一個callback 參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,這樣客戶端就能夠隨意定製本身的函數來自動處理返回數 據了。
聰明的開發者很容易想到,只要服務端提供的js腳本是動態生成的就好了唄,這樣調用者能夠傳一個參數過去告訴服務端「我想要一段調用XXX函數的js代碼,請你返回給我」,因而服務器就能夠按照客戶端的需求來生成js腳本並響應了。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title></title><script type="text/javascript">// 獲得航班信息查詢結果後的回調函數var flightHandler =function(data){ alert('你查詢的航班結果是:piao價 '+ data.price +' 元,'+'餘piao '+ data.tickets +' 張。'); }; // 提供jsonp服務的url地址(不論是什麼類型的地址,最終生成的返回值都是一段javascript代碼)var url ="http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; // 建立script標籤,設置其屬性var script = document.createElement('script'); script.setAttribute('src', url); // 把script標籤加入head,此時調用開始 document.getElementsByTagName('head')[0].appendChild(script); </script></head><body></body></html>
是否是有點奇怪?爲何我此次沒有寫flightHandler這個函數呢?並且居然也運行成功了!哈哈,這就是jQuery的功勞了,jquery在處 理jsonp類型的ajax時(仍是忍不住吐槽,雖然jquery也把jsonp納入了ajax,但其實它們真的不是一回事兒),自動幫你生成回調函數並 把數據取出來供success屬性方法來調用,是否是很爽呀?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Untitled Page</title><script type="text/javascript" src=jquery.min.js"></script><script type="text/javascript"> jQuery(document).ready(function(){ $.ajax({ type: "get", async: false, url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998", dataType: "jsonp", jsonp: "callback",//傳遞給請求處理程序或頁面的,用以得到jsonp回調函數名的參數名(通常默認爲:callback) jsonpCallback:"flightHandler",//自定義的jsonp回調函數名稱,默認爲jQuery自動生成的隨機函數名,也能夠寫"?",jQuery會自動爲你處理數據 success: function(json){ alert('您查詢到航班信息:piao價: '+ json.price +' 元,餘piao: '+ json.tickets +' 張。'); }, error: function(){ alert('fail'); } }); }); </script></head><body></body></html>