天天看點

json、jsonp跨域請求資料小結

         環境:DotNet4.5 MVC4.0

         最近在做項目的時候遇到跨域請求的問題,主要是對json和jsonp的使用,做個小總結,小的初學,請各位大牛輕虐。

        就環境而言呢,實際上項目是部署在同一伺服器上的幾個solution,現在的需求是想要通路另一solution中的API,傳回Json(model,jsonbehavior.allowget)。滿懷自信的寫好ajax,type=“get”,data-type=“json”,url=“xxx.xxx.xxx.xxx/api/func",然後處理下success的json資料,append的到頁面上,啟動,一氣呵成,OK,顯示正常,釋出部署到伺服器,浏覽,資料為空,呵呵了。

        看了下發現我的電腦用的是IE11,伺服器是IE9,浏覽器不相容,好的,找個IE9的電腦,調試下程式,在ajax的error事件裡抛出statusTXT,報”NO Tranport“異常,果斷問度娘,找到一句話,jquery.support.cors=true;啟動,資料出來了,NICE,打完收工。

        第二天bos說IE6報js錯誤,

json、jsonp跨域請求資料小結

蛋碎一地,自己試了下,發現除了IE9+,其他浏覽器均無法顯示資料,Very Very Nice,然後各種調試,get、post和json、html各種組合,全部NO反應,看來跨域請求json資料還是有點不同的,基于同源政策的蛋疼特性,是以轉投jsonp的懷抱。

        研究以後,這裡先說明一下jsonp和json的差別,雖然被jquery打包塞進了ajax的資料類型中,不過嚴格來說jsonp并不是一種資料格式,而是一種資料通路的方式,被某些大牛利用html一些特性做出來主要用于跨域資料傳遞的解決。由于同源政策的限制,頁面使用的資源通常隻能通路本域内有的,但是某些标簽除外,比如說<script>和<iframe>标簽中的src屬性,使得它們可以直接跨域調用資源,比如說引用Jquery.min.js,我們可以直接引用google的js,而jsonp就是利用這種特性來進行跨域資源通路的。

        查了查jquery的api,主要多了個callback參數,用于傳遞回調方法的名稱,大爺的,關鍵部分不說。好吧,先試試,直接把資料格式改成jsonp,啟動,JS報錯,傳回的json資料冒号附近有文法錯誤,缺少分号”;“。咦,難道是我api裡傳回的json資料格式備援?好的,各種精簡,沒有的全部幹掉,需要啥傳回啥,再次運作,一樣報錯,

json、jsonp跨域請求資料小結

好吧,上網查。

        注意到網上的一些處理方法,伺服器接到請求後在js裡生成類似于<script>object{"xxx":"xxx"}</script>的html語句塊,突然意識到上面說的,jsonp是利用<script>的src特性來完成跨域資料通路的,是以這裡傳回的應該是javascript而不是直接傳回json,但是網上是在js裡用createElement生成的html,難道我要在Controller裡手動拼接?nope,這裡用了一個webapi JavaScriptSerializer,使用Serialize方法直接将資料處理為javascript,然後response回去,類似于json api的序列化方法。生成啟動,OK,資料出來了,試了搜狗、火狐、360浏覽器,全部沒有問題,奶奶的,終于可以歇口氣了,上個廁所去,回見。

補充說明:

       經過一段時間的使用,這裡再詳細說明一下jsonp的使用特性,上文已經說明,使用jsonp請求json資料實際上實在請求跨域的js資源,你可以傳回字元串,datatable等等,那麼傳回的資料會作為js加載到頁面當中,比如說我傳回一個string:“hello world”,那麼實際上在頁面的腳本上添加了下面這樣的東西。

<script>
 hello world
</script>      

 同樣,如果我們json的資料那麼它在頁面加載的結果就是:

<script>
{string:"hello world"}
</script>      

 顯而易見,這必然是報錯的結果,我們肯定不能直接在寫js的時候寫一個字元串上去,那麼如何解決這個問題,這就是為什麼要傳一個callback參數過去。如何把這個字元串放到js上而且不報錯,還要為我們所用,那麼需要我們把它當成一個方法的參數傳回來,而這個方法就是我們指定的callback參數,即回調函數。實際上我們可以把這個回調函數先放一邊,假設我們傳回來這樣一個字元串"fun('hello world')",那麼在頁面加載的js就是

<script>
fun("hello world")
</script>      

 那麼我們要做的就是提前定義好一個方法fun(string){},至于json該怎麼用就顯而易見了吧。那麼大多數情況下API可能不是我們自己寫的,我們不能要求那邊每次按我們的要求傳回什麼樣的字元串,是以就要用到callback參數,就是提前把我們想讓他傳回結果後調用的方法傳給他,那麼他就可以通過request解析到這個方法名,然後拼出結果傳回給我們就可以了。

       上面我用了一個webAPI來将json字元串解析為js,然後就可以直接傳回到ajax請求的success(string)方法裡,其實原理是一樣的,隻是某些操作被jquery自動執行了。如果我們不指定callback參數的值,其實jquery會幫我們自動生成一個,類似于“jquery000000000”,後面的這些數字是用來唯一差別的,至于是時間戳還是什麼的我就沒有去研究了,通過上面的webAPI自動幫我們解析,傳回結果,然後這個方法會替代success方法執行,好處就是不用我們自己去想一個方法名了,看起來就和普通的ajax請求很像了。