很多人都把 ASP.NET 當做是一種程式語言,但它實際上只是一個由 .NET Framework 提供的一種開發平台 (development platform),並非程式語言。也可认为ASP.NET是.NET组件,任何.NET语言,例如C#,可以引用该组件,创建网页或Web服务。
為了因應雲端化所誘發的多作業平台整合與開發能力,微軟特別開發一個新一代的 ASP.NET,稱為 ASP.NET vNext,並於 2014 年命名為 ASP.NET 5,但隨後於 2016 年將它更名為 ASP.NET Core,由於架構上的差異頗大,因此未來 ASP.NET 與 ASP.NET Core 將是分別發展與維護,Windows 平台的 ASP.NET 4.6 以上版本仍維持 Windows Only,但 ASP.NET Core 則是具有跨平台 (Windows, Mac OSX 與 Linux) 的能力。
ASP.NET的前身ASP技術,是在IIS 2.0上首次推出(Windows NT 3.51),當時與 ADO 1.0 一起推出,在IIS 3.0(Windows NT 4.0)發揚光大,成為伺服器端應用程式的熱門開發工具,微軟還特別為它量身打造了Visual InterDev開發工具,在1994年到2000年之間,ASP技術已經成為微軟推展Windows NT 4.0平台的關鍵技術之一,數以萬計的ASP網站也是這個時候開始如雨後春筍般的出現在網路上。由於它的簡單以及高度客制化的能力,也是它能迅速竄起的原因之一。
ASP.NET 的原始設計構想,就是要讓開發人員能夠像 VB 開發工具那樣,可以使用事件驅動式程式開發模式 (Event-Driven Programming Model) 的方法來開發網頁與應用程式,若要以ASP技術來做到這件事的話,就必須要使用大量的輔助資訊,像是查詢字串或是表單欄位資料來識別與判斷物件的來源、事件流向以及呼叫的函式等等,需要撰寫的程式碼量相當的多,但 ASP.NET 很巧妙利用表單欄位和JavaScript指令碼把事件的傳遞模型隱藏起來了。
ASP.NET 的事件模型是由 <form runat="server"></form> 以及數個 Hidden Field 組合而成,基於 HTTP 模型的限制,所有的網頁程式在執行結果輸出到用戶端後,程式就會結束執行,為了維護在 ASP.NET 網頁與控制項的狀態資料,因此在輸出 ASP.NET 控制項時,ASP.NET 會將部份狀態資料儲存到網頁的 Hidden Field 中,這類型的狀態資料稱為 ViewState(ID 為 __VIEWSTATE),在伺服器端即會被解譯出狀態與事件資料。在大多數的內建 Web 控制項中都有使用到這個機制,因此在使用大量 ASP.NET Web 控制項的網頁中,會有許多的 ViewState 會存放在網頁中並隨著 HTTP 資料流輸出到用戶端,ViewState 在輸出時,會被加密為一組亂碼字串,其金鑰值定義在電腦中,並且每一個物件都會被序列化 (serialize) 成字串(因此若是自訂物件要放到 ViewState 時,則應要讓它支援序列化),再輸出到 __VIEWSTATE 欄位中,在每次的網頁來回時都會被傳輸,較大的 ViewState 會讓網頁大小膨脹,不利於快速的網路傳輸,不過 ASP.NET 本身有提供將 ViewState 關閉的功能,因此如果控制項不需要狀態保存時,可將它關閉以減少輸出的大小。
在 ASP.NET 運行的時候,經常會有網頁的來回動作 (round-trip),在 ASP.NET 中稱為 PostBack,在傳統的 ASP 技術上,判斷網頁的來回是需要由開發人員自行撰寫,到了 ASP.NET 時,開發人員可以用 Page.IsPostBack 機能來判斷是否為第一次執行(當 ASP.NET 發現 HTTP POST 要求的資料是空值時),它可以保證 ASP.NET 的控制項事件只會執行一次,但是它有個缺點(基於 HTTP POST 本身的缺陷),就是若使用者使用瀏覽器的重新整理功能(按 F5 或重新整理的按鈕)刷新網頁時,最後一次執行的事件會再被執行一次,若要避免這個狀況,必須要強迫瀏覽器清空快取才可以。
來回模式不僅是 ASP.NET 運作時的核心,它也是 ASP.NET 應用程式的一個主要缺點,尤其是在設計複雜度高的頁面時,在網頁中隱藏的 ViewState 的大小會相當大,而在每次的來回動作中,都會傳送 ViewState 在內的表單資訊,大量的 ViewState 會使得傳送的時間拉長,而且每次來回動作都會讓整個網頁被刷新,而出現閃爍的情況(就算在本地端也一樣),但在AJAX技術尚未成熟時,只能夠忍受這種因底層限制所帶來的問題,在ASP.NET AJAX技術發展出來後,透過UpdatePanel成功的緩解了這個問題(但 ViewState 傳送的問題仍然未根本的解決,必須要使用像 Page Method 這樣的方式才能徹底的解決)。
繪製技術
熟悉 ASP 技術的人都知道,程式碼都是混在 HTML 標籤之間,以輸出預期需要的 HTML 指令,這個技術在 ASP.NET 中,由各控制項的繪製 (Render) 機制包裝起來了,繪製機制裝載了 HtmlTextWriter 物件,由它來產生 HTML 指令,它會輸出至 HttpContext 的 Response 輸出資料流中(即 ASP 技術的 Response.Write()),下列程式碼為繪製技術的示例:
狀態管理在單一伺服器上,可以儲存在伺服器的記憶體中,但若是在大型網站中,使用許多的 Web 伺服器來實行負載平衡(Load Balancing)處理時,會有狀態儲存在哪個位置的問題,因此需要有一個可以在每個 Web 伺服器之間做狀態儲存的媒介,像是獨立的伺服器或是資料庫等等。在 ASP.NET 中支援了四種狀態儲存的媒介[6]:
InProc:儲存與 ASP.NET 相同的執行行程中 (in-procedure state),適合單一伺服器的狀態儲存。
StateServer:儲存在 ASP.NET 狀態伺服器 (state server) 中,適合跨伺服器的狀態儲存,但因為它使用的通訊埠,因此在使用上需要注意防火牆的問題。
ASP.NET 是開發 Web 應用程式的基礎架構 (framework),除了它內部的運作方法外,對外也顯露了許多的開發支援,讓開發人員可以利用它來發展出許多強大的 Web 應用程式解決方案。
基礎部件
網頁
ASP.NET 最基礎的底層為網頁 (Page),網頁由 System.Web.UI.Page 類別來提供基礎支援,包含了頁面的事件以及物件繪製的引發點(Page 類別本身是一個 HTTP Handler 的實作品)。ASP.NET 網頁在微軟的官方名稱中,稱為 Web Form,除了是要和Windows Forms作分別以外,同時也明白的刻劃出了它的主要功能:「讓開發人員能夠像開發 Windows Forms 一樣的方法來發展 Web 網頁」。因此 ASP.NET Page 所要提供的功能就需要類似 Windows Forms 的表單,每個 Web Form 都要有一個 <form runat="server"></form> 區塊,所有的 ASP.NET 伺服器控制項都要放在這個區域中,這樣才可以讓 ViewState 等伺服器控制能夠順暢的運作。
在網頁中也可以使用程式碼,以類似於ASP時代的撰寫方式來開發,此種開發方式稱為 inline code,在 ASP.NET 的程式開發模式中,inline code ,要放在 <script runat="server"></script> 區域中,如下列的範例程式:
角色服務與會員服務類似,由 Role 以及其資料提供者 RoleProvider 構成,應用程式使用 Role 所顯露的方法操作,由 RoleProvider 實作提供資料服務,目前內建的 RoleProvider 有來自 Active Directory 或 XML 檔案的 AuthorizationStoreRoleProvider,由 SQL Server 供應資料的 SqlRoleProvider,以及支援 Windows 角色的 WindowsTokenRoleProvider 三種,開發人員可自行實作 RoleProvider 的方法以發展出自訂的角色服務提供者。
設定檔服務是一個特殊的服務,它結合了 .NET Framework 的 CodeDOM 開發模式,以及 System.Web.Profile 命名空間的 ProfileBase、ProfileInfo 與 ProfileManager 等類別,組合出完整的設定檔支援,其資料來源也是以 Provider-based Pattern 為主,由 ProfileProvider 提供,ASP.NET 內建由 SQL Server 資料庫建立的 SqlProfileProvider,其欄位係由開發人員在 ASP.NET 組態檔中自行定義,再由 ASP.NET 動態產生強型別的欄位屬性。
設定檔服務也是作為 ASP.NET 2.0 的網頁組件 (Web Part Framework) 所需要的設定檔儲存支援[11],Web Part Framework 可以讓開發人員可以開發出具備個人化能力 (Personalization) 的網頁配置方案,讓使用者可以用自行新增與拖放的方式來設計自己的網頁佈置,所需要的設定儲存即由設定檔服務處理。
另一個需要和應用程式服務配合使用的功能為 Web 事件架構 (Web Event Framework)[12],它需要由應用程式服務提供資料結構,它也有 Provider-based Pattern,並可以支援數種的事件資料提供者。
延展性支援
除了 ASP.NET 網頁以外,.NET Framework 還提供了兩種可以由開發人員自行發展處理模型的模組,一種是HTTP Handler,另一種則是HTTP Module[13]。
ASP.NET 在一開始的時候是缺乏範本引擎 (template engine) 的,其主因是.NET Framework本身是物件導向,且需要用繼承的方式才能夠延伸功能,大多數的開發人員都是由 System.Web.UI.Page 繼承並定義出新的基礎類別,並撰寫要繪製 HTML 的方法,以及在他們的應用程式中修改以繼承該類別,然而這個方法可能會被用在網站的很多地方,因而會大大的提升混合程式碼與標記的複雜度,這個方法也只能在執行期才能夠以視覺化的方式測試,無法在設計時期視覺化,其他的開發人員總是使用原有的 ASP 方法(即<!-- #include --> 指令)來把每個網頁需要的部份包到網頁中,防止在每個網頁中都要撰寫相同的導覽程式碼。
在 ASP.NET 2.0 中,推出了母板頁面 (master page)的概念[14],它可以讓開發人員先行定義外觀版型 (*.master),再使用它來套用實際執行的網頁,網頁與主版頁面之間以 ContentPlaceHolder 的 ID 做連結,以套用正確的內容到保留區(即由 ContentPlaceHolder 包住的區域)中,開發人員也可以定義在保留區沒有套用時需要顯示的預設內容。在 ASP.NET 3.5 中更進一步的支援設計時期的巢狀主版頁面 (nested master pages),以及把網頁的 HEAD 區塊納入 ContentPlaceHolder 的範圍。
ASP.NET 在 1.x 時,使用的是組件為主的編譯方式,一個網頁只會產生一個組件,這個方式最大的優點,就是可以自由定義命名空間,且在部署應用程式時會比較方便,但由於 ASP.NET 1.x 所處的時代,如果網站是有許多程式碼的情況下(即 DLL 檔很大),載入的速度會變慢,且佔用記憶體的量會很多,當時的記憶體價格也尚未降到現在的水準。因此在 ASP.NET 2.0 開始,另外提供了一個預先編譯(Pre-compilation) 的編譯模型,這個編譯方法會將每個網頁都各自編譯成一個組件,其檔案名稱會是 App_[亂數字串].dll 命名,在編譯時期由 ASP.NET Pre-compilation 工具(aspnet_compiler.exe)給定,優點是可以不必載入過量的程式碼到記憶體中,但缺點則是無法自訂命名空間,而且在更新時必須要更新所有的 DLL 檔以及網頁等,否則會造成名稱不一致,讓 DLL 無法被載入的問題。
早期 ASP.NET 2.0 僅提供預先編譯模式,讓它的缺點很快的被暴露出來,因此微軟也為 ASP.NET 2.0 開發了沿用 ASP.NET 1.x 的編譯模型的工具:Web Application Project,在 Visual Studio 2008 中開始內建,至此,ASP.NET 支援兩種編譯模式的架構抵定。
安全性支援
ASP.NET 的安全性支援分為驗證 (Authentication)與授權 (Authorization)兩個部份。
ASP.NET 1.0 開始支援 Web Service 的開發,是微軟在原生平台上支援 Web Service 發展的第一個實作品,但它卻不是微軟的第一個 Web Service 開發工具實作品[18],.NET Framework 中提供了一個 WSDL.exe,可以連接 Web Service 下載WSDL定義檔,並產生一個 Proxy Class 的原始碼,供用戶端應用程式使用,若是使用 Visual Studio 開發的話,這個動作會由「加入 Web 參考」的動作在背後處理掉。
ASP.NET Web Service 的發展只是平台的基礎,微軟在 Web Service 的開發上提供持續的支援,尤其是在 WS-I (Web Service Interoperability) 組織成立後,為符合 WS-I 的 Web Service 標準,微軟開發了強化 Web Service 的增強套件 Web Service Enhancement (WSE),最新版本為 3.0 版(搭配 ASP.NET 2.0),可支援許多 WS-I 的標準。
ASP.NET Dynamic Data Framework 是微軟在 ASP.NET 3.5 中開發的一組類別庫,封裝在 System.Web.DynamicData 命名空間中,並且配合 ASP.NET Routing Model(網頁繞送功能)讓開發人員可以很簡單的開發出基於 LINQ to SQL 或是 ADO.NET Entity Framework 資料模型的資料庫應用程式。