細細品味ASP.NET
2024-07-10 12:57:04
供稿:網友
asp現在被從頭到腳地重建了,結果就是asp.net。它并不只是asp 4.0,它是一個用于 的全新框架,其中包含了許多新的特性。asp.net提供了更易于編寫、結構更清晰的代碼,這些代碼很容易進行再利用和共享;asp.net使用編譯后的語言,從而提升性能和伸縮性;asp.net使用web表單使開發更直觀,利用面向對象技術促進組件的再利用。另外,asp.net中還包括有頁面事件、web控件、緩沖技術以及服務器控件和對數據捆綁的改進。供 asp.net使用的庫以及在microsoft.net框架中允許通過web 使用客戶商用函數,為程序員提供了更多新的開發機會。
asp.net的優勢
asp.net使代碼更加干凈。現有的asp 應用程序中,不管你將它們寫得怎么樣,結構總是充滿了長長短短的代碼。而asp.net的代碼不僅更容易編寫,而且更加干凈整潔,比asp代碼更易于閱讀。同時,asp.net代碼的結構方式提高了其再利用性和共享性。
asp.net 改進了配置、伸縮性、安全性和可靠性。對于簡單的asp應用程序,配置其實并不算什么問題,但是當你移植到一個利用組件的n層結構中時就會遇到問題。當你對這些應用程序進行配置和維護時,dll 陷阱問題(組件注冊、版本、鎖定的dll等等)就會出現。asp.net中則取消了組件注冊以及dll鎖定,全面使用了xml配置文件,從而解決了這個問題。這樣你只需要執行復制文件的工作就能配置一個web應用程序。
asp.net對各種不同的瀏覽器提供了更好的支持。對于asp開發人員來說,瀏覽器兼容問題好象是一個永恒的問題。你或者為低一級的瀏覽器編寫代碼,例如用html 3.2,或者限制頁面的瀏覽范圍。無線應用程序協議wap設備的引入還會深化這個問題。本文中web表單這部分描述了asp.net是如何解決瀏覽器兼容性問題的。
asp.net 造就了一類新的web應用程序。目前的web應用程序通常都是同一種模式:一套線性應用程序,然后將邏輯植入其中之一。asp.net允許開發人員打破這種單一模式,創造出更加動態而且伸縮性更強的應用程序,這種應用程序能夠更好地滿足公司的商業需求,并提供一個更加豐富的開發環境。
到這里你可能會想,雖然這些目標都很高尚,但是它們會使編寫應用程序變得困難。然后恰恰相反,用asp.net 進行開發要簡單得多!
下面我們就來細細品味一下asp.net的強大特征,包括:
●對編譯語言的支持
●web表單
●跟隨頁面對象的頁面事件
●web控件
●web services
●緩沖技術
●調試和跟蹤
●代碼和內容隔離
●名稱空間的通用庫
●配置
使用經過編譯的語言
現有的asp版本是基于腳本語言的,如vbscript和jscript 。腳本語言本身并沒有什么錯,但是它們有兩大缺陷:它們是解釋型的,并且分類不嚴格。asp.net并沒有完全拋棄腳本語言的概念,它引入了對全編譯語言的支持,使你能夠用visual basic編寫自己的服務器端代碼,例如:
<script language=“vb” runat=“server”>
visual basic的一大優勢是其對嚴格分類變量的支持,因此以下的代碼在asp.net中是成立的:
dim firstname as string
除了visual basic和c++,你還可以使用最新的microsoft語言 c#來編寫服務器端代碼。c# 將c++ 中不實用的部分都去掉了,它更容易理解。用asp.net,編譯動作在頁面第一次裝載時發生。即便代碼是腳本語言,它也會在執行前被編譯,因此 jscript代碼頁面的性能也會得到提高。實際上,這是 .net 框架的一個基本的新特征。以前版本的語言編譯器對數據類型和對象是區別對待的,這就意味著唯一可以進行跨語言開發的就是創建com對象。microsoft .net框架中的通用語言運行時間環境clr允許對已經用通用運行時間支持編譯過的任何代碼進行緊密的交互作用,這就是新的visual basic和c# 編譯器將要做的:創建能在運行時間中被管理的代碼。
這樣做最大的優點是使得真正的跨語言開發成為可能。有了通用運行時間環境clr,你可以用c#創建對象,并在 visual basic中通過繼承功能對它們進行擴展。現在的 visual basic .net支持繼承功能,這樣你就可以在c# 中編寫組件,然后在visual basic中將它們設置成子集。雖然 visual basic、c#和腳本語言是在開始的框架結構中被支持的語言,但是稍后其它語言,如smalltalk、eiffel、pascal等等,也將會被支持。microsoft .net框架的一個優勢就是擴展非常得容易,因此使用一種新的語言僅僅需要為運行時間環境兼容的輸出提供編譯器支持。
web表單
asp.net web forms就是web頁面,同現在你用 asp編寫代碼所做的工作是一樣的。但是還不僅僅如此,asp.net web forms是在一個面向對象的編程模型上設計的,這樣代碼就能夠再利用,并且使應用程序代碼與頁面內容分隔開。在visual basic中,你將一個控件拖曳到一個表單上,然后執行其下的事件程序。在傳統的 asp中,這是不可能的,因為在用戶界面控件和它們的服務器端代碼之間沒有鏈接存在。但是在asp.net中,這樣的一個鏈接是存在的。所以,你可以編寫下面表1所示的代碼,而不用手動從變量表中拖出值:
表1 簡單asp.net web form例程
<html>
<script language=“vb” runat=“server”>
sub submitbutton_click(source as object, e as eventargs)
response.write (òyou entered ò & name.text)
end sub
</script>
<body>
<form method=“post” runat=“server”>
name: <asp:textbox id=“name” runat=“server” /><br>
<asp:button text=“enter”
onclick=“submitbutton_click” runat=“server” />
</form>
</body>
</html>
在表1中有兩點值得注意。第一是在表單上 runat=“server” 屬性和 asp:textbox控件的使用,這可以告訴 asp.net 服務器和客戶都可以使用這些控件。如此使用的控件叫做服務器控件。asp: 用做控件名的前綴,它本身就識別了控件是從哪來的。稍后我將討論這一點。第二個需要注意的細節是onclick事件。開發dhtml 代碼時,你經常要用到 onclick事件,這是為了在瀏覽器中激活一個事件。因為為控件設置了runat=“server” 屬性,所以事件只在服務器上被激活。要對這個例子進行擴展,可以去掉 response.write,然后用一個基于服務器的控件來代替它,比如下面的表2代碼:
表2 使用基于服務器的控件
<html>
<script language=“vb” runat=“server”>
sub submitbutton_click(source as object, e as eventargs)
youentered.text = òyou entered ò & txtname.text
end sub
</script>
<body>
<form method=“post” runat=“server”>
name: <asp:textbox id=“txtname” runat=“server” /><br>
<asp:button text=“enter”
onclick=“submitbutton_click” runat=“server” />
<br>
<asp:label id=“youentered” runat=“server”></span>
</form>
</body>
</html>
這個代碼運行相當好,很象一個傳統的客戶或visual basic表單,代碼也直觀多了。你可以用服務器控件來連接事件過程和基于服務器的代碼。這些基于服務器的控件向瀏覽器發送純 html內容,其中不再含有客戶端腳本。實際上,這其中一個重要的設計目的就是要堅持使用固有的 html 3.2元素代碼以提供最大可能的瀏覽器兼容性。比如說,表2中的代碼生成了以下html:
<html>
<body>
<form name=“htmlform2" method=“post” action=“test.aspx” id=“htmlform2">
<input type=“hidden” name=“__viewstate” value=“a0z664351470__x”>
name: <input name=“txtname” type=“text” id=“txtname”><br>
<input type=“submit” name=“button5" value=“enter”>
<br>
<span id=“lblyouentered”></span>
</form>
</body>
</html>
生成的代碼是符合 html 3.2標準的。它執行一個標準投遞,將用戶輸入發送回同一個文件。這里沒有對服務器狀態進行維護,也沒有客戶端腳本對狀態進行維護。隱含的域執行對控件狀態的維護,這意味著在頁面的“提交-返回”之間,控件能自動恢復狀態,而不需要任何編程干預。雖然 asp.net web控件的默認輸出是符合html 3.2標準的內容,但是對于更高級的瀏覽器如microsoft internet explorer 5.0,也可以輸出為dhtml格式。這樣你就能只使用一套服務器控件來編寫頁面,允許控件根據瀏覽器決定發送哪種類型的輸出,從而允許你將發送 dhtml的控件和客戶端腳本用到最新版本的internet explorer中,將純 html 3.2內容發送到其它瀏覽器中。
頁面事件
在此前我提到 asp.net已經被從頭到腳地重寫了,但是我并沒有指出它是按照面向對象的思路重建的。在對象樹的頂部是page對象,即頁面對象,asp.net的每個控件、應用程序和頁面都是從這個對象中繼承來的,也就是說每個頁面都是頁面對象的一個例示。頁面的load (裝載)事件是一個非常重要的事件,如下面的表3代碼所示:
表3 使用頁面事件
<html>
<script language=“vb” runat=“server”>
sub page_load(source as object, e as eventargs)
‘ code to run when page loads
end sub
sub submitbutton_click(source as object, e as eventargs)
‘ code to run when button is clicked
end sub
sub page_unload(source as object, e as eventargs)
‘ code to run when page unloads
end sub
</script>
<form runat=“server”>
<asp:button text=“enter” onclick=“submitbutton_click” runat=“server” />
<asp:label id=“youentered”/>
</form>
</html>
在這里你看到了以前在visual basic中經常見到的同樣的 load/unload (裝載/卸載)過程。 當頁面被裝載時,load事件被激活,這時所有基于服務器的控件都可用。在與用戶的交互作用過程中會生成其它事件。最后,當頁面被卸載時激活 unload事件。
web控件
你可能會擔心,象 <asp:textbox>這樣的控件代表了一套需要你熟練運用的全新控件。不過,它們并不難學,因為它們在html中都有對應者。例如,對于一個很簡單的文本框,在html 中,你是這樣做的:
<input type=“text” value=“your name”></input>
而相應的web 控件是這樣的:
<asp:textbox text=“your name” runat=“server” />
在這兩者中,你立刻就能注意到的是web 控件通過代碼“asp:”名稱空間來識別,并且同在xml中一樣,使用斜線來結束元素。你不是必須使用xml的格式,你也可以使用html格式,用一個分號來結束標記:</asp:textbox>。但是你會發現,xml格式被用在許多代碼舉例中,并且代碼字數也較簡潔。名稱空間必須要使用,它負責識別文本框textbox 控件來自哪里。所有的標準web控件都是 asp名稱空間的一部分。當編寫自己的控件時,這一點變得很重要。
textbox控件相對于標準的輸入框好象沒有多少優勢,但是你應該考慮一下面的三個輸入控件:
<input type=“text” ...>
<input type=“password” ...>
<textarea rows=“5" ...>
它們都是用于html輸入的,但是并沒有一致性。但是如果使用下面的,是不是更簡單一些呢?
<asp:textbox runat=“server” ...>
<asp:textbox textboxmode=“password” ...>
<asp:textbox rows=“5" ...>
你可以看到,一個簡單控件包含了html中三個控件的功能,而且更易記憶、更易編碼。
asp.net攜帶了5大類 web控件:
• 與html相對應的固有控件
• 在頁面上提供數據流的列表控件
•提供更豐富的ui(用戶界面)內容和功能的rich控件
• 完成各種表單驗證的確認控件
• 為 wap設備封裝wml的移動控件
固有的服務器控件與 html控件相同,但是更加合理了,可提供更為一致的用途。這些控件包括linkbutton(鏈接按鈕)、imagebutton(圖象按鈕)、hyperlink(超級鏈接)、textbox(文本框)、checkbox(復選框)、radiobutton(單選框)、dropdownlist(下拉列表)、listbox(列表框)、image(圖象)、label(標簽)、panel(面板)、table(表格)、tablerow(表格行)、tablecell(表格單元)。
列表控件包括repeater(轉發器)、datalist(數據列表)和datagrid(數據柵格)。列表控件還包括radiobuttonlist(單選框列表)和 checkboxlist(復選框列表),這樣就使創建單選框和復選框的列表變得簡單。
rich控件包括calendar(日歷)和adrotator(廣告旋轉)。calendar控件為低級的瀏覽器輸出純html,為高級瀏覽器輸出dhtml(如 internet explorer 5.0)。adrotator輸出圖象,它有內置的旋轉代碼。
確認控件包括requiredfieldvalidator(請求域確認)、 compare validator(比較確認)、rangevalidator(范圍確認)、regularexpressionvalidator(規范表達確認)、customvalidator(顧客確認)和validationsummary(確認摘要)。這些控件為開發人員在表單處理中建立確認提供了簡單的途徑。
有關移動控件的信息現在還沒有發布,但是可以肯定它們有助于構造激活wap的web站點。
編寫新的控件
你并不一定只局限于使用這些系統提供的控件,自己編寫控件也相當簡單。例如,如果想要一個控件來封裝兩個文本框(可能是名和姓的輸入域),就可以這樣來編寫代碼:
<asp:panel runat=“server”>
<asp:textbox id=“txtfirstname” text=“first name” runat=“server” />
<asp:textbox id=“txtlastname” text=“last name” runat=“server” />
</asp:panel>
可以把這個代碼保存在文件 name.aspc (注意這個新擴展名)中,并將其作為一個web表單控件來對待。接著,就可以向 web表單中增加以下內容:
<%@ register tagname=“namecontrol” tagprefix=“foo” src=“name.aspc” %>
<form>
<foo:namecontrol runat=“server”/>
</form>
這樣你就可以很容易地創建可以再利用的控件了。這真實很美好 ;-) 你還可以直接在visual basic或 c#中創建控件,允許它們成為其它控件的子類,并且呈現任何它們所要求的輸出。因為控件是用名稱空間來識別的,因此在控件之間應該是沒有沖突的。實際上,控件甚至可以使用同一個名字,只要它們在不同的名稱空間中就行。你會感覺到,這使得 asp.net非常具有擴展性,并且使編程環境變得越來越豐富。實際上有一個很大的提供豐富控件的第三方市場。
數據捆綁控件
新的web控件之一是數據柵格datagrid,這是用于顯示成套數據的內置支持控件。為了從sql生成的數據中產生一個 html表格,你只需要創建 ado+對象,并執行指令來獲取數據以作為柵格的數據源,比如下面的表4代碼:
表 4 davesgrid1.aspx
<%@ import namespace=“system.data.sql” %>
<html>
<script language=“vb” runat=“server”>
sub page_load(sender as object, e as eventargs)
dim mycommand as sqlcommand
mycommand = new sqlcommand(òselect * from products”,
òserver=localhost; database=advworks; uid=sa”)
datagrid1.datasource = mycommand.execute
datagrid1.databind
end sub
</script>
<body>
<asp:datagrid id=“datagrid1" runat=“server” />
</body>
</html>
所需要做的就是將數據捆綁到數據柵格,然后就生成了一個整潔的html表格:
數據捆綁并不局限于來自數據庫的數據,你還可以捆綁到hash表格、數組、其它服務器控件、頁面的適當層,幾乎什么都可以。如果默認的欄目不合適,還可以對其進行定制,讓其顯示你所感興趣的部分:
<asp:datagrid id=“datagrid1"
autogeneratecolumns=“false” runat=“server”>
<property name=“columns”>
<asp:boundcolumn headertext=“ name” datafield=“productname”/>
<asp:boundcolumn headertext=“description”
datafield=“productdescription”/>
</property>
</asp:datagrid>
使用 boundcolumn 控件選擇一個簡單的欄目,并指定欄的標題和這欄要捆綁到哪里。 autogenerate=“false” 屬性負責確保柵格不會為你創建所有的欄目。如果想更復雜一些,也可以為這個欄目使用一個模板。
此前提到的repeater和datalist控件也支持模板,這樣就允許對控件的外觀進行定制。repeater實際上并沒有外觀,你必須要提供 ui,這就意味著必須要使用一個模板。相反,datalist控件是一個捆綁到數據的列表,有一個默認的外觀和豐富的行為。為這兩個控件添加模板的方法是一樣的:
<asp:datalist is=“datalist1" runat=“server”>
<template name=“headertemplate”>
here”s your list of titles<br>
</template>
<template name=“itemtemplate”>
<%# databinder.eval(container.dataitem, “title”) %> <br>
</template>
</asp:datalist>
有了這個模板template,你就可以指定用哪些 html控件來組成數據捆綁控件的每一部分。有5個模板的名字可以與 datalist控件一起使用:headertemplate用于控件的最頂端部分,itemtemplate 用于各個項目,alternating-item-template用于其它項目,separatortemplate用于各個項目之間的區域,footertemplate用于控件的底部。
這個系統的好處在于:對于如何顯示界面,有大量的控件可以使用。進一步使用產品列表,你就能用表7中的代碼來生成下圖所示的輸出:
表 7 davesgrid2.aspx
<asp:datalist id=“mydatalist” repeatcolumns=“2" runat=“server”>
<template name=“itemtemplate”>
<table cellpadding=10 style=“font: 10pt verdana”>
<tr>
<td width=1 bgcolor=“bd8672"/>
<td valign=“top”>
<img align=“top”
src=“<%# databinder.eval(container.dataitem,“productimageurl”) %>“ >
</td>
<td valign=“top”>
<b>name: </b>
<%# databinder.eval(container.dataitem,”productname”) %><br>
<b>description: </b>
<%# databinder.eval(container.dataitem,“productdescription”) %><br>
<b>price: </b>
<%# databinder.eval(container.dataitem,”productprice”, “$ {0}”) %>
</td>
</tr>
</table>
</template>
</asp:datalist>
這個代碼相當簡單,除了前面顯示的 datalist代碼外,不再需要更多的東西。代碼里有一點值得注意,就是你可以規定出現的欄數,列表會自動處理欄的包裝。這樣就只需要一點格式化代碼,web頁面就得到了極大的改進,而不再使用以前web 頁面上的傳統柵格。
開發web services(web服務)
在internet上作為服務發布的軟件是 web services的核心。 asp.net提供了一個 web services的基礎構造環境,從而使開發人員能夠為這個服務模型創建服務。
現在我們來跟蹤一個簡單的例子。比如說你要從一個在線書商那里購買書籍,他們有一個跟蹤系統,使你能夠看到自己定單的狀態。書商用一個陸地運輸公司來運輸你訂的貨。這個運輸公司也有一個跟蹤系統。這樣,為了得到你的定單的確切狀態,你要查看兩個站點。如果書商能夠將它自己的定單狀態和運輸公司的狀態信息一同顯示出來,就會很方便。
web services就允許你在web上將客戶商用函數暴露給公眾,例如包裹跟蹤細節。編寫一個對象,將其方法作為uri暴露出來,uri返回一個xml數據。現在書商可以調用運輸公司的跟蹤服務,并將跟蹤的結果合并到它自己的定單跟蹤應用程序中。以下是運輸公司如何用 c#創建一個服務的代碼:
<%@ webservice language=“c#” %>
using system.web.services;
public class shipping {
[webmethod]
public string orderstatus(string ordernumber) {
// code here to retrieve order details from data store
return status;
}
}
以上代碼保存于 tracking.asmx文件中,位于運輸公司 web站點的應用程序目錄中。這樣書商就可以使用多種方法來調用這個 web services了。比如使用 http-get,參數同查詢字符串一同被傳遞:
http://orders.ups.com/orders/tracking.asmx/orderstatus?ordernumber=bru123
書商還可以使用 http-post,方法的參數作為表單值在post體內傳遞。或者還可以使用http-soap,方法的參數被包裹在一個工業標準 xml格式中。
現在用戶只需要在書商那里查詢他們的定單細節,書商的 web 應用程序就會從運輸公司那里收集跟蹤信息,然后同書的狀態一起返回。書商也可以將它的定單狀態細節作為一個web services暴露出來,讓其它人使用它。
web services的偉大之處在于,它允許你暴露一個服務而不必暴露數據或所有的商業規則。當自動提供商業服務的同時,代碼和數據都是安全的。在以后幾年里,隨著b2b方案的可利用,web services的市場會得到快速的增長。