關於JQuery 中$.ajax函數利用jsonp實現Ajax跨域請求ASP.NET的WebService成功獲取數據的案例
開發環境:Visual Studio 2010 SP1
部署環境:Window 7 SP1+IIS7
現在的JQuery中$.ajax方法支持跨域讀取json數據了,原理是利用一個叫做jsonp的概念。當然,究其本質還是通過script標簽動態加載js,似乎這是實現真正跨域的好方法。
$.ajax的用法JQuery手冊已經寫得很詳細,參考手冊就可以了,很簡單。需要指出的一點是$.ajax利用的jsonp需要客戶端與服務端作出配合。
先整理幾種之前嘗試過但是失敗的方案吧!
- 方案一:我嘗試過自己寫一個Ajax函數去請求WebService,JavaScript代碼沒有報錯.但是回調函數沒有執行,證明服務器(IIS)沒有響應,我用了個手段測試下是否有請求到該WebService,在其初始化時,創建一個txt文件,寫入任意數據表示它請求到,然后在其方法內也做了個類似手段測試,結果證明自己寫的Ajax函數並沒有請求WebService,為什么?我也不清楚,如果有碰到過這樣情況的朋友並且已經解決的請告知我,謝謝.
- 方案二:我剛開始的時候,以為是IIS的環境或權限問題,我改為Visual Studio測試環境發布該WebService,結果一樣,沒有請求.
- 方案三:上Google查了很多資料,包括MSDN,cnblogs,JQuery等官方示例,但是官方示例只給了片段,代碼不完全,而且他們url地址填的是本地地址,而不是遠程(網絡)地址,甚至不同的資料上其$.ajax函數內的格式有不同的寫法,都試過了,失敗告終.
- 方案四:后來看到有人說我的WebService沒有加上類特性[System.Web.Script.Services.ScriptService]以及方法特性[System.Web.Script.Services.ScriptMethod],我很納悶,這遠程訪問(跨域調用)跟這特性有什么關系?不過我還是照做,加了上去,事實證明,一點意義都沒有.
成功方案:
其成功解決問題的幾個重要因素如下:
1. 由於WebService默認不支持Get請求,所以要在Web.config配置文件內的<system.web>節點內添加如下元素:
1 <system.web> 2 <webServices> 3 <protocols> 4 <add name="HttpGet"/> 5 <add name="HttpPost"/> 6 </protocols> 7 </webServices> 8 </system.web>
有些網友沒有在這里問,而是通過QQ問我問題。
我在幫他們遠程調試的時候,沒注意看,后來才發現原來問題是他們把這段配置放在客戶端程序,而不是web service服務程序。郁悶..
在此強調下:是放在web service網站的web.config里面,而不是放在客戶端程序的web.config里。
2. 在請求的URL加參數jsoncallback=?,注意這里jsoncallback=?是關鍵所在!其中?符號會被JQuery自動替換成其它的回調方法名稱,具體過程和原理我們這里不予理會。我們關心的是jsoncallback=?起什么作用了?原來jsoncallback=?被替換后,會把方法名稱傳給服務器。我們在服務器端要做什么工作呢?服務器要接受參數jsoncallback,然后把jsoncallback的值作為JSON數據方法名稱返回。
3. 設置dataType類型為”jsonp”
WebService代碼如下:
1 using System.Web; 2 using System.Web.Services; 3 /// <summary> 4 ///UserService 的摘要說明 5 /// </summary> 6 [WebService(Namespace = "http://tempuri.org/")] 7 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 8 public class UserService : System.Web.Services.WebService 9 { 10 [WebMethod] 11 public void GetLoginId(string loginId) 12 { 13 string callback = HttpContext.Current.Request["jsoncallback"]; 14 bool bl= true;//這是我調用業務邏輯層(BLL)的一個方法 15 //返回一個布爾(boolean)值 16 //現在我省略掉,直接賦值true 17 HttpContext.Current.Response.Write(callback + 18 "({result:'" + bl + "'})"); 19 //關於result這詞是你自己自定義的屬性 20 //會作為回調參數的屬性供你調用結果 21 HttpContext.Current.Response.End(); 22 } 23 }
aspx頁面及javascript腳本代碼如下:
1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 2 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 4 <html xmlns="http://www.w3.org/1999/xhtml"> 5 <head runat="server"> 6 <title>測試</title> 7 <script type="text/javascript" src="Scripts/jquery-1.7.2.js"></script> 8 <script type="text/javascript"> 9 //Document加載完畢后初始化方法 10 $(function Init() { 11 $("#TxtLoginId").bind("blur", CkLoginId); 12 }); 13 //帳號驗證及提示 14 function CkLoginId() { 15 var Id = $("#TxtLoginId"); 16 $.ajax({ 17 url: "http://localhost:5311/UserService.asmx/GetLoginId?jsoncallback=?", 18 dataType:"jsonp", 19 data:{"loginId":Id.val()}, 20 success:OnSuccess, 21 error:OnError 22 }); 23 } 24 function OnSuccess(json) { 25 alert(json.result); 26 } 27 function OnError(XMLHttpRequest, textStatus, errorThrown) { 28 targetDiv = $("#data"); 29 if (errorThrown || textStatus == "error" || textStatus == "parsererror" || textStatus == "notmodified") { 30 targetDiv.replaceWith("請求數據時發生錯誤!"); 31 return; 32 } 33 if (textStatus == "timeout") { 34 targetDiv.replaceWith("請求數據超時!"); 35 return; 36 } 37 } 38 </script> 39 </head> 40 <body> 41 <form id="form1" runat="server"> 42 <table border="0" cellspacing="0" cellpadding="0" width="100%"> 43 <tr> 44 <td> 45 <asp:Label ID="LblLoginId" runat="server" Text="帳 號" ClientIDMode="Static"></asp:Label> 46 <asp:TextBox ID="TxtLoginId" runat="server" ClientIDMode="Static"></asp:TextBox> 47 </td> 48 </tr> 49 </table> 50 </form> 51 </body> 52 </html>
運行結果:

轉載的朋友,請不要刪除以下行,對此,表示感謝!!!
原文鏈接:http://www.cnblogs.com/VAllen/archive/2012/07/12/JQueryAjaxRegion.html
