在asp.net ajax中updatepanel比較常用,原本需要重新整理的操作套在updatepanel中就成了ajax操作了,挺帥!但ajax也是支援與Xml Web Service互動的,這種方法更像是傳統的ajaxpro和其他ajax架構,如jquery,magicajax,extjs的風格,但MS總是獨樹一幟,誰讓他的產品設計能力那麼高呢!我輩恐怕望塵莫及亞.閑話少敘,下面簡單講述下asp.net ajax如何調用xml web service,熟悉的朋友就略過吧
1. 建立一個支援Asp.Net Ajax的網站或者網路應用程式,我使用的是vs2008,在vs2008中,如果建立的網站支援.net framework 3.5就有ajax的預設支援,這陳芝麻,爛穀子的事情,也不多說。
2. 建立好項目之後,在網站根目錄中添加一個Web服務UserService.asmx,在UserService.asmx中添加如下方法:
[WebMethod]
public bool UserAdd(string userName,string pwd)
{
return true;
}
注意服務類上部要添加Attribute
[System.Web.Script.Services.ScriptService]
3. 然後把default.aspx中的ScriptManager修改成如下代碼的德性:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="UserService.asmx" />
</Services>
</asp:ScriptManager>
下面我們就在頁面中建立用Ajax消費這個UserService的代碼:主要包括如下:
<h2>Ajax調用Xml Web Service樣本1</h2>
<div style="border: 1px solid Black; width: 50%; padding: 10px;">
<table class="style1">
<tr>
<td>
使用者名稱:
</td>
<td>
<input id="txtName" type="text" />
</td>
</tr>
<tr>
<td>
密碼:
</td>
<td>
<input id="txtPwd" type="password" />
</td>
</tr>
<tr>
<td>
</td>
<td>
<input id="Button2" type="button" value="提交" onclick="userAdd()" />
</td>
</tr>
</table>
</div>
在<head></head>添加如下指令碼
function userAdd()
{
var name = $get("txtName").value;
var pwd = $get("txtPwd").value;
AjaxWs.UserService.UserAdd(name,pwd,userAddCallBack);
}
function userAddCallBack(res)
{
alert(res);
}
4. 好,現在一個簡單的ajax調用web service的範例程式碼已經搞定,羅索了不少,其實簡單的不能再簡單,運行頁面,點擊提交按鈕,效果如下:
表示成功。一般人這一步都會成功的。二般的除外亞,:)
一些正常,那是不是到這裡就萬事大吉,ajax萬歲!web service真好!下面是略加思考之後的問題
問題一:
上面的Xml Web Service沒有任何保護,如果UserAdd是一個資料庫插入操作,那這個操作往往系統只被經過授權的人才能調用成功。以前看有朋友討論ajax如何調用帶有SoapHeader的xml web service,細細想想,其實沒什麼必要!js是用戶端的東西,是放出去收不回來的玩意,天知道使用者是哪路貨色 ,如果將身份資訊試圖通過js傳遞給SoapHeader,那密碼被截獲的可能性就比較大。正確的做法其實是Session .我們知道Web Service方法中添加一個[WebMethod(EnableSession=true)]就能使用Session了,Session這傢伙專門用於保持會話,有這樣一個 認識之後,新增一個網路服務方法,這個方法實現功能和起初的UserAdd一致,只是添加上訪問限制
[WebMethod(EnableSession=true)]
public bool UserAddSecurity(string userName, string pwd)
{
if (Session["UserID"] == null)
{
return false;
}
return true;
}
在頁面中將AjaxWs.UserService.UserAdd(name,pwd,userAddCallBack);更改為AjaxWs.UserService.UserAddSecurity(name,pwd,userAddCallBack);點擊提交按鈕,會發現彈出結果為false!
在頁面中添加一個按鈕,點擊這個按鈕類比登陸,點擊代碼為:
protected void Button3_Click(object sender, EventArgs e)
{
Session["UserID"] = "jillzhang";
}
點擊登陸按鈕後,再次點擊提交,便可以返回true。 這樣便限制了使用者對xml web service的訪問。達到瞭解決問題一的目的。
問題二:
這個問題涉及到xml web service架構的缺陷,這個缺陷在WCF中已經有所更正和彌補。我們知道web service是一種強度公開和共用的技術,之所以稱之為服務,必然是提供給其他應用程式所使用。但事實上,有很多服務是服務於局部或者特殊個體的,而不是理想中的福士。而在原來老的xml web service中,wsdl的發布與網路服務的發布是綁在一起的,我將.asmx部署到iis中,那在這個.asmx後加上?wsdl就能訪問服務的wsdl。wsdl是對服務的描述,知道它,便能開發客戶代理,從而消費服務,但這樣有問題:我的服務只想讓局部或者特殊的幾個人知道 ,其他人根本不想讓其訪問到。這就麻煩了。我發布.asmx,wsdl就發布。而wsdl的發現依靠的是UDDI,通過下面的一段描述:
UDDI 如何被使用
假如行業發布了一個用於航班比率檢測和預訂的 UDDI 標準,航空公司就可以把它們的服務註冊到一個 UDDI 目錄中。然後旅行社就能夠搜尋這個 UDDI 目錄以找到航空公司預訂介面。當此介面被找到後,旅行社就能夠立即與此服務進行通訊,這樣由於它使用了一套定義良好的預訂介面。
如果遍曆UDDI目錄,不難發現WSDL,發現WSDL後便可以開發用戶端與服務互動。這可不是好事情,在問題一中,用授權的方法可以解決一種問題,但假如我的服務是這樣的,它返回伺服器目前時間,這個方法對於我網站的使用者而言是公開的,如果生硬的加上Session,有些麻煩。但這個服務我只希望我自己的ajax能訪問,不希望別人發現並調用,但原來的xml web service架構的確不能滿足這個需求。如果被一個攻擊者發現,他可能會根據公開的wsdl開發用戶端,然後不停的DDOS攻擊,災難!
上面這個問題對於原來的web service,我還是沒有好的解決方案,當然不代表沒有解決方案。有朋友知道,勞煩指教。
但對於WCF架構,就充分考慮到上面這個問題了。看看下面老的Xml Web Service架構與WCF架構之間的對比:
1) 老架構
2) 新架構
區別很明顯,老架構MEX與業務耦合度非常高,儼然一體,而新的架構卻將兩者份將開來,分而不僵,反而會增加靈活性。如果是WCF開發的服務,在發布網站的時候,完全可以通過配置,將MEX終結點去掉,這樣就可以解決上面的問題。具體執行個體下文討論,有點困了,睡!
附上樣本項目:
/Files/jillzhang/AjaxWs.rar