關於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 //現在我省略掉,直接賦值true17 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:OnError22 });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