通過Ajax的getJSON()方法和post()方法獲取JSON數據


  GET請求和POST請求均是HTTP中最常用的請求協議,而Ajax提供了便捷的方法,getJSON和post就是其中的兩個異步請求方法。從名稱上就可以看出getJSON方法是專門用來獲取JSON數據的異步請求,而post方法也可以通過POST協議向服務器發送各種數據對象。我在最近開發的一個小項目中需要異步請求獲取服務的JSON數據對象時也就很自然地想到了這個方法。由於我是剛開始學習使用ASP.NET MVC技術,對於Ajax更是不夠了解,所以,難免不能合理的根據使用場景使用合適的方法,下面就來說說我遇到的問題以及我的處理方式。

  我的使用場景:

  1. 項目使用技術框架:ASP.NET MVC4
  2. 開發工具:VS2013
  3. 布局頁將頁面布局分為左側導航頁和右側內容頁,導航頁和內容頁均為分部視圖
  4. 內容分部視圖script腳本中在jQuery的ready方法中直接使用getJSON方法在頁面完全加載后獲取后台服務器上的JSON數據,由於是很簡單的小項目,就直接在視圖中編寫了腳本,並直接請求控制器中的動作方法
  5. 內容頁有復選框列表和提交按鈕以及其他功能所需元素
  6. 運行瀏覽器為IE11

  遇到的問題(現象):

  聲明:

  為了方便描述,這里簡化場景為左側一個頁面導航鏈接link_A,右側內容頁面中有一個復選框列表checkBoxList,一個提交按鈕submit。

  功能簡單的為:

  1. 點擊link_A后頁面導航至當前內容頁,此時將會根據配置結果顯示checkBoxList的內容,如果之前被設置為選中的項將會被勾選。
  2. 點擊submit按鈕將提交checkBoxList的設置結果,並在成功提交后刷新當前頁(其中實現方式這里不作描述,以簡化描述的問題)。
  3. 提交的數據對象與獲取的數據對象為同一個JSON數據對象,方便起見為其命名為jsonModel

  

  起初使用getJSON方法獲取服務端提供JSON數據的動作方法時可以實現基本功能,在成功提交后也能正確顯示最后的設置結果(如之前只勾選了選項A,現在勾選的是A和B,提交到后台的也是A和B)。

  代碼示例:

// GetJSONModel 控制器中用於獲取 JSON 數據的動作方法
$.getJSON("@Url.Action("GetJSONModel")", null, OnSuccess);

  此時的現象是:

  1. 點擊link_A鏈接時頁面加載完成后得到的jsonModel對象的內容為我最后一次設置的前一個狀態(即之前只勾選的選項A);
  2. 清除瀏覽器的緩存,然后再次點擊link_A鏈接將會得到正確的結果(即最后一次勾選的A和B均能正確被勾選);
  3. 直接F5刷新瀏覽器,重新發送請求也會得到正確的結果(即最后一次勾選的A和B均能正確被勾選)。

  原因:如果不清除緩存而直接點擊link_A鏈接時將不調用控制器中的GetJSONModel方法,所以我認為這和緩存有關。可當直接F5刷新時又能夠正確顯示結果,也會調用GetJSONModel方法(此時未清除緩存),這又說明並不完全是緩存的問題。

  解決辦法:使用post方法可以滿足我這里需要的每一次請求都會調用后台動作方法。示例代碼如下:

$.post("@Url.Action("GetJSONModel")", null, OnSuccess);

  總結:

  這里提供了這種場景下的解決辦法,也能清楚的看到這兩種請求的在實際使用中的一些效果區別:

  • 對於使用getJSON方法發送的GET請求只有在清除緩存后導航或整體刷新頁面(如使用F5刷新)時會調用后台動作方法獲取最新的數據
  • 對於post方法發送的POST請求可以在每一次的請求都會調用后台動作方法獲取所需的數據

  但是,以我現在對這兩個協議的了解還不能解釋清楚GET請求所帶來的前面現象中描述的那個問題。不過有一點很清楚,就是在項目中使用時一定要注意是否應該使用GET請求,如果不能很好的應用這種請求將會帶來很痛苦的教訓,甚至災難性的破壞——因為它是安全的的請求,HTTP中又會肯定其合法性,如果請求的數據會改變服務器的狀態,那后果就可想而知了。

  這次遺留的關於使用GET請求時並不是什么情況下都可以訪問請求的對象的問題希望有一天我能夠真正的搞明白,那時候我會進一步闡明其中緣由。當然,如果哪位大神能夠指點一二甚好,我也很期待學習。

  好了,就到這吧,希望我的問題描述的足夠簡單、清除,易於理解。

 

-----------------------------分割線下方將解釋之前遺留的問題----------------------------------------

 

遺留問題釋疑:

  本文前面描述的現象中存在一個遺留問題,就是關於GET請求不會每一次都會調用后台請求的控制器方法。現在經過查找資料及多次試驗,最終弄明白是怎么回事了。其實還是和緩存有關,即對於多數瀏覽器,都會將請求所獲取的數據進行緩存,如果在瀏覽器會話期間將不再進行請求(所以,這也就是為什么我在重新導航至該請求地址時一直不會訪問目標方法,並更像獲取的數據——刷新瀏覽器將會是一次新的會話——這不同於點擊導航連接重新訪問,所以這樣可以)。

  解決辦法有多種,之前我給出的改用post()方法是其中之一。既然這和瀏覽器的緩存有關系,所以可以使用Ajax禁用內容緩存來實現;另外,在瀏覽器會話期間重新訪問同一個URL將不再進行請求,那么可以為請求的URL設置一個隨機的參數值。詳見如下示例:

  • 禁用內容緩存:
$.ajax({
            type: "GET", url: "@Url.Action("GetJSONModel")", cache: false, success: OnSuccess });
  • 為請求URL提供隨機參數值:
$.getJSON("@Url.Action("GetJSONModel")", { random: Math.random() }, OnSuccess);

  補充:

  好了,現在我想看到這里就能明白是怎么回事並知道該如何處理這個問題了。但是,還是要提醒一下,這也和很多資料和書籍里提到的一樣,關於該如何選擇GET和POST,在什么時候用哪一種請求更好。這是我們在項目中應該注意的一點。關於這一點的一般說法是:

  GET請求用於安全交互,同一個請求可以發起任意多次而不產生額外作用(即副作用)。POST請求則用於不安全交互,提交數據的行為會導致一些狀態的改變。我想着樣說的話有些人應該還是不太好理解,尤其是像我一樣剛學習這一技術的菜鳥——我就很長一段時間被這個“安全”和“非安全”給搞得暈頭轉向。所以,簡單來說就是如果我們需要獲取一些只讀的數據,尤其是在當前瀏覽器會話期間內的(不在同一會話期間內、給予同一URL隨機參數或禁用緩存的除外)則應該使用GET請求;如果請求所獲取的數據是已經發生變化了的,或將會改變程序狀態的操作,這應該使用POST請求。如果實在搞不清楚的話,很多大神也會建議我們直接使用POST請求。

  之所以將GET應用於獲取只讀數據的情況下,是因為其為安全交互,將被HTTP服務認為是合法請求,如果這個請求將改變服務器狀態,那很有可能會帶來災難性的后果,所以,對於GET請求一定要慎重使用。建議我們如果請求將會帶來程序狀態的改變最好使用POST請求。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM