摘要:了解如何利用 ASP.NET Whidbey 更輕松地使用代碼。Code 目錄會自動為您的站點編譯代碼,而預編譯會使部署工作更容易。
下載本文的源代碼。(請注意,在示例文件中,程序員的注釋使用的是英文,本文中將其譯為中文是為了便于讀者理解。)
目錄
簡介
新的模塊化代碼模型
\Code 目錄
利息計算器
預編譯支持
在位預編譯
部署預編譯
IntelliSense 無處不在!
小結
簡介
即將推出的新版 Microsoft® ASP.NET 介紹了大量新功能和改進功能,它的代號為 ASP.NET Whidbey,是根據新版 Microsoft® Visual Studio® .NET 的代號命名的。其中的某些功能利用了基礎 Microsoft® .NET Framework 版本(ASP.NET Whidbey 就是基于該版本構建的)中的新功能。在這些功能當中,最有用的功能集之一與代碼編譯有關。
本文介紹 ASP.NET Whidbey 編譯模型的主要更改、這些更改對編寫 ASP.NET 應用程序的影響,以及如何利用這些更改。
改進的功能和新的編譯功能可以分為以下四個基本方面:
- 對模塊化代碼模型的改進。
- 新的 Code 目錄。
- 新增的對預編譯 ASP.NET 應用程序的支持。
- Microsoft® IntelliSense® 增強功能。
新的模塊化代碼模型
默認情況下,使用 Visual Studio .NET 2002 或 2003 開發的站點使用一種稱為“模塊化代碼”的功能將可視元素(HTML 標記、控件等)從與 UI 相關的編程邏輯中分離開來。當開發人員創建一個新 Web 窗體(例如 foo.aspx)時,Visual Studio 會自動創建一個相關的 Codebehind 類文件,該文件名稱的前一部分與 Web 窗體相同,后面是 .vb 或 .cs(取決于項目使用的語言)。類文件將通過 @ Page 指令的 Codebehind 和 Inherits 屬性與 Web 窗體相關聯。
類文件包含事件處理代碼(包括用于將事件處理程序綁定到相應事件的代碼),以及每個控件(通過 Visual Studio Web 窗體編輯器添加到 .aspx 文件中)的分離聲明。編譯(生成)Web 應用程序項目后,其中的所有 Codebehind 類都將編譯到一個 .NET 程序集中,該程序集將放置到 Web 應用程序的 \bin 目錄中。Web 窗體頁本身會在運行時動態進行編譯,并且每個 Web 窗體均繼承自與其相關的 Codebehind 類。有關 Visual Studio .NET 2003 和 ASP.NET 1.1 中的模塊化代碼模型的詳細信息,請參閱 MSDN Library 文章 Web Forms Code Model(英文)。
雖然最初的模塊化代碼模型理論上不錯(誰不希望將 UI 元素與編程邏輯相分離呢?),但它還是有一些缺點:
- 需要重新生成。在 Visual Studio .NET 中,運行時不會自動編譯 Codebehind 類,因此對 Codebehind 類的任何更改都需要重新生成整個項目以應用這些更改。(請注意,您可以通過 @ Page 指令的 src 屬性指定對模塊化代碼文件進行動態編譯,但默認情況下 Visual Studio .NET 不會執行此操作。)
- 共享開發問題。由于項目中的所有 Codebehind 類都編譯到了一個程序集中,所以很難讓多個開發人員同時開發一個項目而不會遇到瓶頸問題。
- 代碼易被破壞?丶瑫r通過聲明(在 .aspx 頁面中)和編程(在 Codebehind 類中)的方式存在,如果這兩組控件沒有正確同步,很容易使代碼遭到破壞。
- 復雜程度增加,而且缺少單文件支持。在 Visual Studio .NET 中,很多用于提高生產率的功能(包括 IntelliSense 語句完成)都需要使用模塊化代碼。遺憾的是,這些功能通常會在 Codebehind 類中添加大量相對復雜的代碼,這就產生了代碼易被破壞的問題,因為更改 Visual Studio .NET 插入的代碼很容易破壞頁面。
了解到這些缺點后,負責開發 ASP.NET 和 Visual Studio .NET Whidbey 的小組決定重新考慮模塊化代碼模型。新的模塊化代碼模型利用了 Microsoft® Visual Basic® .NET 和 C# 中稱為局部類(在 C# 中稱為局部類型)的新功能。局部類使您能夠在多個文件中定義一個類的不同部分。編譯時,由編譯器將這些部分再組合到一起。ASP.NET Whidbey 使用 @ Page 指令中新的 CompileWith 和 Classname 屬性來標識要與 .aspx 頁面結合的 Codebehind 局部類。通過利用局部類,再進行一些其他更改,ASP.NET 小組可以實現以下目的:
- 無需在 Codebehind 類中編寫控件聲明和事件綁定代碼(在控件聲明中通過聲明的方式綁定事件)。
- 允許運行時同時對 Web 窗體頁和 Codebehind 類進行動態編譯,無需再為細微的更改而重新生成整個項目。
- 減少共享開發中的文件爭用現象。
- 對于使用模塊化代碼文件的開發人員以及喜歡單文件開發(所有代碼和標記均包含在 .aspx 文件中)的開發人員,均可獲得相同的 IDE 體驗。
下面給出了模塊化代碼模型更改前后的不同視圖。以下代碼只是在使用模塊化代碼添加新的 Web 窗體(在 Visual Studio .NET Whidbey 中稱之為具有代碼分隔的 Web 窗體)時,由 Visual Studio 創建的默認代碼:
Visual Studio .NET 2002/2003
WebForm1.aspx:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="TestWebApp_121602.WebForm1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>WebForm1</title> <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"> <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1"> <meta name=vs_defaultClientScript content="JavaScript"> <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"> </head> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> </form> </body> </html>
WebForm1.aspx.vb:
Public Class WebForm1 Inherits System.Web.UI.Page #Region " Web 窗體設計器生成的代碼 " '此調用是 Web 窗體設計器所必需的。 <System.Diagnostics.DebuggerStepThrough()> _ Private Sub InitializeComponent() End Sub '注意:以下占位符聲明是 'Web 窗體設計器所必需的。 '請勿刪除或改變其位置。 Private designerPlaceholderDeclaration As System.Object Private Sub Page_Init(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Init 'CODEGEN:此方法調用是 Web 窗體設計器所必需的。 '請勿使用代碼編輯器修改它。 InitializeComponent() End Sub #End Region Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load '此處放置用于初始化該頁面的用戶代碼 End Sub End Class
Visual Studio .NET Whidbey
Default.aspx:
<%@ page language="VB" compilewith="Default.aspx.vb" classname="ASP.Default_aspx" %> <html> <head runat="server"> <title>無標題頁</title> </head> <body> <form runat="server"> </form> </body> </html>
Default.aspx.vb:
Imports Microsoft.VisualBasic Namespace ASP Expands Class Default_aspx End Class End Namespace
從上面的示例可以清楚地看到,由 Visual Studio .NET Whidbey 生成的代碼更加清晰、易讀。無需犧牲拖放功能或 IntelliSense 來實現此目的。
\Code 目錄
ASP.NET Whidbey 中的另一個非?崆覍嵱玫男鹿δ苁窃黾恿 \Code 目錄。\Code 目錄與 \bin 目錄類似,是 ASP.NET 使用的一個特殊目錄,但它與 \bin 目錄又有所不同:\bin 目錄用于存儲由應用程序使用的預編譯程序集,而 \Code 目錄用于存儲要在運行時進行動態編譯的類文件。這使您可以將業務邏輯組件、數據訪問組件以及其他組件的類存儲在應用程序中的某個位置,并從任意頁面使用這些類。因為這些類是在運行時動態編譯的,而且會被包含 \Code 目錄的應用程序自動引用,所以在部署項目之前不需要生成項目,也不需要明確添加類引用。您可以放心地對組件進行更改,然后使用簡單的 XCOPY 或拖放操作進行部署。除了簡化組件的部署和引用外,\Code 目錄還極大地簡化了本地化過程中使用的資源文件 (.resx) 的創建和訪問過程,以及為 WSDL 文件 (.wsdl) 自動生成和編譯代理類的過程。
為了更好地說明上述操作的實現過程,讓我們先來看幾個示例。在第一個示例中,我們將看到如何創建一個簡單的業務組件,以及如何從 Web 窗體頁對其進行訪問。
利息計算器
首先,我們打開 Visual Studio .NET Whidbey,創建一個名為 Compilation 的新 Web 站點。創建 Web 站點之后,IDE 應與圖 1 類似。
圖 1:Visual Studio .NET Whidbey Web 站點
然后,我們將 \Code 文件夾添加到該 Web 站點,添加方法為右擊該項目,然后選擇 New Folder(新建文件夾)。此文件夾必須命名為 Code,但名稱不區分大小寫。添加文件夾后,我們可以添加一個新的類文件:右擊 \Code 文件夾,單擊 Add New Item...(添加新項...),然后在 Add New Item(添加新項)對話框的 Templates(模板)窗格中選擇 Class(類)項。將類命名為 CalculateInterest.vb。然后添加用于計算利息的代碼(將其添加到 Class 和 End Class 語句之間):
Public Function CalcBalance(ByVal Prncpl As Integer, _ ByVal Rate As Double, _ ByVal Years As Integer, _ ByVal Period As Integer) As String Dim BaseNum As Double = (1 + Rate / Period) CalcBalance = _ Format(Prncpl * System.Math.Pow(BaseNum, _ (Years * Period)), "#,###,##0.00").ToString End Function
創建組件類后,我們需要修改 Default.aspx 頁面以提供用來輸入數據的字段,還需要調用組件的 CalcBalance 方法。為了簡單起見,Default.aspx 的完整列表顯示如下(請注意,Default.aspx 使用單文件代碼模型)。
Default.aspx:
<%@ page language="VB" %> <script runat="server"> Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Dim Calc As New CalculateInterest Label6.Text = "$" & _ Calc.CalcBalance(Convert.ToInt32(TextBox1.Text), _ (Convert.ToInt32(TextBox2.Text) / 100), _ Convert.ToInt32(TextBox3.Text), _ Convert.ToInt16(Dropdownlist1.SelectedValue)) Label6.Visible = True End Sub </script> <html> <head runat="server"> <title> 利息計算器</title> </head> <body> <form runat="server"> <asp:label id="Label1" runat="server">P本金 ($):</asp:label> <asp:textbox id="TextBox1" runat="server"> </asp:textbox> <br /> <asp:label id="Label2" runat="server">利率 (%):</asp:label> <asp:textbox id="TextBox2" runat="server"> </asp:textbox> <br /> <asp:label id="Label3" runat="server">年數:</asp:label> <asp:textbox id="TextBox3" runat="server"> </asp:textbox> <br /> <asp:label id="Label4" runat="server">復利頻率:</asp:label> <asp:dropdownlist id="Dropdownlist1" runat="server"> <asp:ListItem Value="1">每年</asp:ListItem> <asp:ListItem Value="4">每季</asp:ListItem> <asp:ListItem Value="12">每月</asp:ListItem> <asp:ListItem Value="365">每日</asp:ListItem> </asp:dropdownlist> <br /> <asp:label id="Label5" runat="server">結余: </asp:label> <asp:label id="Label6" visible="false" runat="server"></asp:label> <br /> <asp:button id="Button1" runat="server" text="計算" onclick="Button1_Click" /> </form> </body> </html>
在設計視圖中,修改后的 Default.aspx 應與圖 2 類似。
圖 2:設計視圖中的 Default.aspx
需要注意是,當您在用于調用組件類的 <腳本> 塊中鍵入代碼時,將獲得完整的 IntelliSense 語句完成(包括組件類),如圖 3 所示。這是在 Visual Studio .NET 2003 基礎上的一大改進,Visual Studio .NET 2003 不支持服務器端 <腳本> 塊中的 IntelliSense。
圖 3:源視圖中的 IntelliSense
瀏覽 Default.aspx 會生成圖 4 中所示的輸出。填入本金、利率和年數,然后單擊 Calculate(計算),輸出結果應與圖 5 類似。
圖 4:Default.aspx 的初始輸出
圖 5:計算后的輸出
資源文件
如果您以前在 Visual Studio .NET 2002 或 2003 中使用過 Web 應用程序,您一定已經注意到每次創建新 Web 窗體頁時,除了 .aspx 頁以及 .vb 或 .cs 模塊化文件之外,Visual Studio 還會創建一個具有 .resx 擴展名的匹配文件(即 WebForm1.aspx.resx)。與大多數 Web 開發人員一樣,您可能也會忽略或試圖刪除這些文件,因為它們的用途和/或用法并不是很直觀。簡言之,這些 .resx 文件稱為“資源文件”,主要用于存儲各個版本的資源,例如用于本地化的不同語言的文本字符串。
在 Visual Studio .NET 2002 和 2003 中,資源文件需要作為生成項目進程的一部分添加到項目程序集中,并且需要導入兩個命名空間,創建一個 ResourceManager 對象,并調用其 GetString 方法以訪問資源字符串。
在 \Code 目錄的幫助下,Visual Studio .NET Whidbey 中的資源訪問過程變得非常簡單,如下面的示例所示。
我們先從創建資源文件開始,還是使用上一個示例中的項目。首先,右擊剛才創建的 Compilation Web 站點,然后單擊 Add New Item...(添加新項...)。在 Add New Item(添加新項)對話框中,選擇 Assembly Resource File(程序集資源文件)模板,將資源文件命名為 strings.resx,然后單擊 Open(打開)。strings.resx 文件的默認視圖應與圖 6 類似。
圖 6:在 XML 編輯器中編輯資源文件
將以下項添加到數據表中(可以將“comment”(注釋)、“type”(類型)和“mimetype”(MIME 類型)列保留為空):
名稱 | 值 |
txtColorPrompt | 請選擇一種顏色: |
txtColorResponseRed | 您選擇了紅色! |
txtColorResponseGreen | 您選擇了綠色! |
txtColorResponseBlue | 您選擇了藍色! |
現在重復上述過程,添加一個名為 strings.en-GB.resx 的新資源文件,并將以下項添加到其數據表中,然后保存文件(因為我們沒有添加 txtColorResponse* 的項,所以所有客戶機都將使用 strings.resx 中的這些項的值):
名稱 | 值 |
txtColorPrompt | 請選擇一種顏色: |
現在,為了充分利用 Code 目錄的神奇作用,我們需要將這兩個 .resx 文件從 Web 站點的根目錄拖到 Code 目錄中。完成上述操作后,將得到類似圖 7 的結果。
圖 7:Code 目錄中的 .resx 文件
為了說明現在使用創建的資源文件是多么簡單,我們將一個 Web 窗體添加到項目中,方法如下:右擊 Web 站點節點,然后單擊 Add New Item....(添加新項...)。在 Add New Item(添加新項)對話框中,選擇 Web 窗體,將頁面命名為 ColorPicker.aspx,然后單擊 Open(打開)。修改此頁面,使其與以下列表匹配。
ColorPicker.aspx:
<%@ page UICulture="en-GB" language="VB" %> <script runat="server"> Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Label1.Text = Resources.strings.txtColorPrompt End Sub Sub Submit_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Label1.ForeColor = _ System.Drawing.Color.FromName(Dropdownlist1.SelectedValue) Select Case Dropdownlist1.SelectedValue Case "紅色" Label1.Text = Resources.strings.txtColorResponseRed Case "綠色" Label1.Text = Resources.strings.txtColorResponseGreen Case "藍色" Label1.Text = Resources.strings.txtColorResponseBlue End Select Dropdownlist1.Visible = False Submit.Visible = False End Sub </script> <html> <head runat="server"> <title>顏色選取器</title> </head> <body> <form runat="server"> <asp:label id="Label1" runat="server">Label</asp:label> <asp:dropdownlist id="Dropdownlist1" runat="server"> <asp:listitem value="Red">紅色</asp:listitem> <asp:listitem value="Green">綠色</asp:listitem> <asp:listitem value="Blue">藍色</asp:listitem> </asp:dropdownlist> <asp:button id="Submit" text="提交" runat="Server" onclick="Submit_Click" /> </form> </body> </html>
當從瀏覽器中瀏覽 ColorPicker.aspx 時,默認輸出與圖 8 類似。如果從為英國用戶設置的系統中瀏覽此頁面(您可以通過將頁面的 UICulture 屬性設置為“en-GB”并保存頁面來模擬此情形),輸出將與圖 9 類似(請注意,我們已經在“colour”中添加了 u)。
圖 8:ColorPicker.aspx 的默認輸出
圖 9:英國系統的 ColorPicker.aspx 輸出
請注意,在 ASP.NET Whidbey 中訪問資源文件只需要一行代碼。因為將資源文件放到 Code 目錄中后,即可自動嵌入和引用該資源文件,所以不需要引用任何命名空間或程序集,也不需要為訪問資源字符串創建對象。而且 ASP.NET 還可以確定應該使用哪個資源文件(基于用戶瀏覽器的設置),因此我們不需要在運行時對此進行判斷并作出相應的響應。ASP.NET 可以幫助我們完成這一切。
預編譯支持
ASP.NET Web 窗體的優勢之一就是增加動態編譯后,您可以很輕松地更改 .aspx 頁,保存更改時頁面將動態更新,而不需要重新編譯(只要不使用模塊化代碼)。但動態編譯并不是對每個應用程序都適合,而且第一次訪問某個應用程序時,動態編譯會導致瀏覽器的初始性能降低。另外,很多時候您可能希望部署一個沒有源代碼的應用程序。
如果您遇到上述情況,您會更高興地了解到 ASP.NET Whidbey 具有支持預編譯 Web 站點的功能。ASP.NET Whidbey 支持兩種預編譯模式:在位預編譯和部署預編譯。
在位預編譯
在位預編譯使您可以對 Web 站點中的所有頁面進行手動批編譯。這也是用戶在您的應用程序中首次單擊某個頁面后發生的操作(前文提到的后一種情況除外),用戶只需坐下來等待批編譯完成。
使用在位預編譯有兩個主要原因:首先,它可以避免第一次請求頁面時批編譯的性能降低;其次,它使您可以“先于”用戶發現編譯錯誤。
在位預編譯也很容易實現,只需瀏覽到 Web 站點的根目錄,添加特定的處理程序名稱 precompile.axd(熟悉 ASP.NET 跟蹤功能的用戶會發現該名稱與 trace.axd 處理程序的名稱類似):
http://localhost/mywebsitename/precompile.axd
其中 mywebsitename 是您 Web 站點的名稱。預編譯站點之后,對站點內頁面的請求也應隨即完成,而不會有任何編譯滯后。
部署預編譯
第二種預編譯模式使您可以創建整個 Web 站點的可執行版本,部署這種版本不需要任何源代碼(包括 HTML 和其他靜態文件)。因此,部署預編譯可以防止別人隨意訪問由代碼表示的知識產權信息。生成的程序集和 Stub 文件集可以通過 XCOPY、FTP、Windows 資源管理器等部署到生產服務器上。
為了預編譯站點以進行部署,ASP.NET Whidbey 提供了一個名為 aspnet_compiler.exe 的命令行實用程序。要在文件系統 Web 站點上調用 ASP.NET 預編譯器,需要打開一個命令窗口,瀏覽到 .NET Framework 的安裝位置(<Windows>\Microsoft.NET\Framework\<版本>),然后輸入以下命令:
aspnet_compiler /v /<websitename> -p <source> <destination>
其中 <websitename> 為 Web 站點的名稱(即在瀏覽器中輸入的名稱),<source> 和 <destination> 為兩個文件系統路徑,分別指向要編譯站點的位置以及編譯后的版本應輸出至的位置。以我們的 Web 站點為例,輸入的命令如下所示(請注意下面是一條命令):
aspnet_compiler /v /Compilation -p c:\WebSites\Compilation c:\WebSites\Compilation_Compiled
如果要查看 ASP.NET 預編譯器的所有可用選項,只需輸入以下命令:
aspnet_compiler /?
請注意,某些命令行選項要求 Web 站點必須為有效的 Microsoft® Internet 信息服務 (IIS) 應用程序才能正常工作。
如果在 Microsoft® Windows 資源管理器中瀏覽至目標目錄,您會看到預編譯 Web 站點后將生成一個包含 bin 目錄的站點,bin 目錄中包含一些程序集和描述性文件,以及大量與原始頁面同名的 Stub 文件,但不包含代碼(包括 HTML 和可執行代碼)。如果瀏覽此站點,輸出與原始站點的輸出相同。請注意,不能在已進行部署預編譯的站點上使用在位預編譯,原因很簡單,因為它已經被預編譯過了。
IntelliSense 無處不在!
對于 Visual Studio .NET 2002 和 2003,最令我頭痛的問題之一(相信很多開發人員也有同感)就是對 IntelliSense 和其他用于提高生產率的功能的支持不一致。希望在 HTML 視圖中將控件從工具箱中拖到頁面上嗎?還做不到。事實上,在 HTML 視圖中根本看不到工具箱的 Web 窗體面板!要在 .aspx 頁面上寫入內嵌代碼而不是使用模塊化代碼?可以做到,但必須放棄 IntelliSense、拖放功能以及其他更多功能。最后,正如我最近在 MSDN ASP.NET Developer Center 上發表的文章中提到的,在 Visual Studio .NET 2002 或 2003 中獲得自定義控件的設計時支持需要跨越層層障礙,包括有點粗糙但奏效的 XSL 修改。
令人高興的是,ASP.NET Whidbey 中實現了編譯模型的統一,所有這些問題也都迎刃而解。在 Visual Studio .NET Whidbey 中,可以寫入內嵌代碼或使用新的模塊化代碼模型,還能獲得控件拖放、IntelliSense 語句完成以及所有以前您希望使用卻因編碼方式局限而無法使用的那些可以提高生產率的功能。另外,對自定義服務器控件和 Web 控件的設計時支持有了很大的改進,包括為源視圖(HTML 視圖在 Visual Studio .NET Whidbey 中的等效視圖)中的自定義控件增加了 IntelliSense 語句完成。
小結
ASP.NET Whidbey 中對編譯模型的更改,以及 Visual Studio .NET Whidbey 中相應功能的改進無疑是一個巨大的飛躍,不僅為開發人員提供了所需的靈活性,還使他們可以充分利用 IDE 提供的可以提高生產率的功能。大大簡化的模塊化代碼模型將使該功能更有用、更簡捷,而新增的對內嵌代碼的完全支持顯然會受到那些希望所有代碼都位于一個 .aspx 文件中的開發人員的歡迎。
相信 \Code 目錄會大大提高生產率,對于那些從事發展迅速的中小型項目的開發人員,以及那些因為編譯過程過于復雜而無法完成工作的開發人員來說尤其如此。它還為訪問業務邏輯組件、資源文件、WSDL 文件以及其他資源提供了一種更為直接、簡單的方法:通過自動編譯、嵌入或創建這些資源的代理并自動引用它們,只需很少的代碼即可訪問這些資源。
預編譯功能使開發人員可以輕松地提高其站點的初始性能,如果需要,還可以通過提供功能完備的 Web 應用程序(不包含源代碼或 HTML)為重要的知識產權信息添加保護措施。
最后,集所有功能于一身的 Visual Studio .NET Whidbey 無疑會為開發人員帶來非凡的體驗,他們不僅能從內嵌代碼模型和模塊化代碼模型中獲得完全的 IntelliSense 支持,還能查看給定頁面的所有視圖,開發工作不會再因工具限制而局限于某一種樣式。
文章來源于領測軟件測試網 http://www.kjueaiud.com/