Asp.Net Ajax的两种基本开发模式
Asp.Net Ajax的兩種基本開發模式
引言
最近花了一些時間,將微軟Asp.Net官方的Ajax視頻全部看了一遍,地址是http://www.asp.net/learn/ajax-videos/,視頻大多都很短,8至15分鐘的居多,有講述AjaxControlToolkit中控件用法的,也有講述Asp.Net Ajax常見的應用場景和技巧的。
本文介紹了使用Asp.Net Ajax做開發時兩種最常見的與服務端進行交互(客戶端請求服務端執行邏輯,服務端返回結果)的開發模式。第一種我姑且稱為UpdatePanel模式,第二種稱為Web Service(WCF Service)模式。
開始前的一些準備
對于這些文章,我假設大家都已經安裝好了Asp.Net Ajax Extension 和 Asp.Net Ajax Control ToolKit 這兩個組件。其中Asp.Net Ajax Extension已經包含在了.Net Framework 3.5中,而Ajax Control Toolkit可以去這個位置下載:http://www.codeplex.com/AjaxControlToolkit/Release/ProjectReleases.aspx?ReleaseId=16488 。因為我使用的是VS2008,所以Ajax Extension無需安裝,而Ajax Control Toolkit我安裝到了GAC(Global Assembly Cache,全局程序集緩存)中,因此文章所附代碼的Bin目錄不會包含任何的dll組件。如果你想運行代碼,可以像我一樣將Ajax Control Toolkit安裝到GAC中,或者針對自己的情況(VS2005或者VS2008,私有程序集部署還是GAC部署)對代碼進行一些簡單的修改和配置。
如果你想安裝到GAC中,假設你將AjaxControlToolkit.dll拷貝到了“C:\”下,那么可以打開“VS2008命令提示符”,然后輸入下面的命令,按回車:
gacutil -i C:\AjaxControlToolkit.dll
除此以外,還有兩點需想要說明。如果你想要在頁面的CodeBehind中使用AjaxControlToolkit中定義的類型,那么需要在Web.config中進行一下配置,假設你和我一樣采用的是GAC部署,那么Web.Config的設置為:
<system.web>
??? <compilation debug="false">
??????? <assemblies>
??????????? <add assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28F01B0E84B6D53E"/>
??????????? <!- 其余略 -->
??? </compilation>
</system.web>
在VS2008(VS2005)中,你可以將AjaxControlToolkit安裝到工具箱(Toolbox)中,但是在安裝好以后,當你向頁面拖放一個控件時,控件默認的前綴是cc1,并且會在頁面頂部自動生成一行控件的聲明,類似于這樣:
// 自動在頁面頂部產生的聲明
<%@ Register Assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
// 頁面中控件的樣式
<cc1:AutoCompleteExtender> ... </cc1:AutoCompleteExtender>
這樣讓人感覺頁面很不清爽,除此以外,cc1也沒有任何的含義。為了解決這個問題,我們也可以在Web.Config進行一下設置:
<system.web>
??? <pages>
??????? <controls>
??????????? <add assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" namespace="AjaxControlToolkit" tagPrefix="ajaxControlToolkit" />
??????????? <!-- 其余略 -->
??????? </controls>
??? </pages>
<system.web>
如果你和我一樣經過上面三個步驟的設置的話,那么在Web站點Bin目錄中不會有任何的程序集,另外頁面頂部也不會再有控件的聲明,同時,拖放控件到頁面中時,它的代碼將是這樣子的:
<ajaxControlToolkit:AutoCompleteExtender> ... </ ajaxControlToolkit:AutoCompleteExtender>
本文以及所有Asp.Net Ajax相關的文章,都假設你采用了和我相同的配置。
Asp.Net Ajax - UpdatePanel模式
現在考慮一個最簡單的范例,頁面上放置一個Label控件、一個Button控件,當我們點擊Button控件的時候,將Label控件的文本更新為當前時間,這里的關鍵是更新時間的代碼位于服務端,而非使用Javascript在客戶端來完成。盡管這里服務端的代碼僅僅是更新一下時間,但在實際中卻可以執行任何的服務端操作。
UpdatePanel是是大家熟悉的一種方式了,即是在頁面拖放一個UpdatePanel,將需要用Ajax方式進行更新的控件放在UpdatePanel之內,在本例中是Label控件。可以將Button控件也放置在UpdatePanel之內,也可以不放置。如果UpdatePanel內不放置Button控件,則需要設置UpdatePanel的Triggers節點,其中包括一個ControlID屬性和EventName屬性,用于指定哪個控件的哪個事件可以觸發了一個PostBack。本例中ControlID自然是Button的ID,而EventName則為Click。也就是說當Button的Click事件觸發時,進行PostBack操作。下面是aspx頁面的主要代碼:
<asp:ScriptManager ID="ScriptManager1" runat="server">
?</asp:ScriptManager>
?當前時間:
?<asp:UpdatePanel ID="UpdatePanel1" runat="server">
??? ?<ContentTemplate>
??????? ?<asp:Label ID="Label1" runat="server" Text="[未設置]"></asp:Label>
??? ?</ContentTemplate>
??? <Triggers>
??????? <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
??? ?</Triggers>
?</asp:UpdatePanel>
?<br />
?<asp:Button ID="Button1" runat="server" οnclick="Button1_Click" Text="更新時間" />
而在后置代碼中,我們只需要像平常的Asp.Net開發一樣,編寫Button控件的Click事件處理程序就可以了:
protected void Button1_Click(object sender, EventArgs e) {
??? ?Label1.Text = DateTime.Now.ToLongTimeString();
?}
OK,現在一切都已經就緒了,如果你運行這個頁面,并且點擊Button,會看到Label的值變為了最新的時間,而且沒有因為PostBack所產生的頁面閃動,即是人們常說的無刷新更新頁面。這可能是實現一個Asp.Net Ajax的最簡單范例了。但是它的問題是什么呢?當我們點擊Button的時候,在服務端執行了一個完整的Asp.Net 頁面生命周期,和你不使用UpdatePanel更新頁面沒有任何的區別。可以做一個測試,在頁面在拖放一個Label,ID為Label2,然后在Page_Load中寫入下面代碼:
protected void Page_Load(object sender, EventArgs e) {
??? if (!IsPostBack) {
??????? Label2.Text = DateTime.Now.ToLongTimeString();
??? } else {
??????? Label2.Text = DateTime.Now.ToLongTimeString();
??? }
}
然后在Page_Load一行設置斷點,接下來運行調試,會發現每次你點擊Button按鈕的時候,都會運行else{...}中的語句,說明每次頁面都會執行Page_Load方法。這說明使用這種方式時,服務器端的開銷是比較大的。這里還可以發現一個有趣的現象,盡管服務器執行了為Label2.Text賦值的語句,但是頁面上Label2卻并沒有更新。如果想要更新它,那么需要將它也放置到UpdatePanel中,這里我們可以在頁面上重新拖放一個UpdatePanel,然后把Label2放置進去。然后我們再點擊Button,會發現Label1和Label2都進行了更新。這里又引出了一個有趣的問題:回想一下前面,我們只為第一個UpdatePanel設置了Triggers節點,而并沒有為后來新添的UpdatePanel設置Triggers節點,但是對一個UpdatePanel的更新也會影響到另一個。有的時候這種情況是我們所需要的,但更多時候不是,我們可能希望對于Label2的更新由其他控件的其他事件觸發。此時,可以將第二個UpdatePanel的UpdateMode屬性設為“Conditional”,就避免了受到其他UpdatePanel提交的影響,這個值默認為“Always”。
下面是此時Aspx頁面的代碼:
<!-- 上面相同 -->
<hr /><br />
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
?<ContentTemplate>
??? ?<asp:Label ID="Label2" runat="server" Text="[未設置]"></asp:Label>
?</ContentTemplate>
</asp:UpdatePanel>
以上這些就是一種最常見的Asp.Net Ajax開發模式了,我們看到它如何實現,也看到了它的缺陷:每次客戶端的操作,都會在服務端執行一次完整的頁面生命周期,加重了服務器的負擔,同時客戶端和服務端的通信過程中也會傳遞完整的http協議內容,增大了網絡流量。我們也應該看到它的優點:實現起來非常的簡單,操作上基本等同于通常的Asp.Net開發,所使用的控件也為Asp.Net服務器控件(Server Control,這里相對于HTML控件而言)。
Asp.Net Ajax - Web Service模式
還有一種方式就是Web Service模式了,客戶端不再提交頁面,而只是發送Web Service請求,并對收到應答進行處理。由于這里采用了異步方式,所以客戶端在發送WebService請求之后無需等待。采用這種方式服務端不會執行生命周期,往返的數據量也減到了最小。但缺點就是需要手動編寫一些代碼。我們來一步步看下如何完成,因為WCF是下一代Windows平臺通信的基礎,集成了Web Service和Remoting這兩大技術,所以我們采用WCF來創建服務。
首先選擇“添加新項”,然后選擇“啟用了AJAX的WCF服務”,輸入名稱SimpleService,這樣會在站點中添加一個SimpleService.svc文件,在App_Code中創建一個SimpleService.cs,還會在Web.Config中添加相關的配置。我們只需要改動一下App_Code中的SimpleService.cs下的代碼:
public class SimpleService
{
??? [OperationContract]
??? public string GetCurrentDate(string clientValue) {
??????? string rtn = "Server Time :" + DateTime.Now.ToLongTimeString() + "<br />";
??????? rtn += "Client Value(round trip): " + clientValue;
??????? return rtn;
??? }
}
SimpleService還用一些特性修飾了,我將它取消掉了以節省空間。方法接受一個字符串clientValue,然后獲取服務器時間,最后返回clientValue。這段代碼看上去沒有什么特別之處,但是注意到我在Client Value旁加了一個括號,寫著“round trip”,對于Ajax程序來說,這個值由客戶端發送,最后再返還給客戶端,進行了一趟由客戶端到服務端,再到客戶端的周游。
為了要讓javascript可以調用這個Web服務,我們需要在aspx頁面中對它進行注冊,拖放也一個ScriptManager到頁面上,然后向下面這樣進行設置:
<asp:ScriptManager ID="ScriptManager1" runat="server">
??? <Services>
??????? <asp:ServiceReference Path="~/SimpleService.svc" />
??? </Services>
</asp:ScriptManager>
接下來我們新建一個Pattern2.aspx頁面,在上面拖放三個HTML標記。一個span,一個input(Button),一個input(Text)。注意,是客戶端HTML標記,不含有runat="server"的,從這里已經可以看到一個很大的不同,我們使用的是客戶端HTML控件。接著在input(Button)上雙擊,會自動生成Javascript腳本,此時aspx頁面的主要代碼如下:
<input id="txtSample" type="text" style="width:120px" /><br />????? ???
<span id="spnTime">[未設置]</span><br />
<br />
<input id="Button1" type="button" value="更新時間" οnclick="return Button1_onclick()" />
最關鍵是接下來要編寫的javascript代碼,我先將它貼出來,然后再進行解釋:
<script language="javascript" type="text/javascript">
function Button1_onclick() {
??? var context = "Callback Values";??????????????? // 傳給回調函數
??? var clientValue = $get("txtSample").value;????? // 獲得TextBox的值
??? SimpleService.GetCurrentDate(clientValue, OnComplete, OnFailed, context);??
??? return true;
}
function OnComplete(args, context){
??? alert(context);
??? var span = $get("spnTime");
??? span.innerHTML = args;
}
function OnFailed(args){
??? alert("更新日期失敗!");
}
</script>
首先看這個Button1_onclick()方法,我們先聲明了一個context,這個content很類似于在C#的委托變量上調用BeginInvoke()方法時的最后一個參數,這個值用于傳遞給回調函數,以方便進行一些處理。接著我們獲取了input(Text)中輸入的值,保存在了clientValue中。然后調用了Web服務,其中第一個參數就是上面定義的GetCurrentDate()時的參數,我們傳入了clientValue,第二個參數是OnComplete是成功時的回調函數,第三個是OnFailed是失敗時的回調函數,最后一個參數我們傳遞了context,可以將它交由回調函數處理。因為是異步操作,所以沒有在這里獲取GetCurrentDate()方法返回值,而是通過回調函數OnComplete的參數對返回值進行了傳遞。
接下來看OnComplete()函數,其實我們最需要搞清楚的就是它的兩個參數:第一個args即為Web服務方法GetCurrentDate()的返回值;而第二個參數,即為調用GetCurrentDate()時傳遞的最后一個參數。在方法內部,我們使用alert()顯示了context的值,隨后將Web服務的返回值顯示在了span中。OnFailed()僅僅是提示用戶更新失敗。
接下來在頁面上點擊Button,應該可以看到下面的效果:
我們再次在Page_Load的位置設置斷點,然后啟動調試,會發現當我們使用這種方式時,點擊Button服務端并沒有再次執行頁面生命周期,而參與客戶端/服務端往返的數據也是最少量的(僅往返必需數據),因此,雖然采用這種方式我們需要編寫一定量的javascript代碼,但是卻能夠顯著地提高站點的性能。
總結
這篇文章簡單的講述了使用Asp.Net Ajax進行開發時常見的兩種方式,使用UpdatePanel + 服務器控件;或者是使用 Web Service + HTML標記 + Javascript,并且這兩種方式的實現方式和效果做了簡要的說明。
感謝閱讀,希望這篇文章能給你帶來幫助!
轉載于:https://www.cnblogs.com/JimmyZhang/archive/2008/11/05/1327709.html
總結
以上是生活随笔為你收集整理的Asp.Net Ajax的两种基本开发模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sharepoint ECMA
- 下一篇: mongodb 入门笔记