作者:朱明中
前言
初學者在學習 ASP.NET 時,多由入門書籍所傳授之控制項使用方法來設計應用程式,表面上看起來是很快完成應用程式,但是當要改變應用程式行為或者是要更進一步發展功能時,往往會 無所適從,原因就是對 ASP.NET 了解的程度不高,對底層並不夠了解,或者有如霧裡看花般無法窺其全貌,這對於進一步發展 Web Application 是一種無形的阻礙,而且若要建立高等級的應用程式時,將會有如浮砂築高塔般,埋藏許多影響應用程式的例子,所以在初學者邁向進階程度時,這是必須要做的功 課。
什麼叫做 Web Application?
Web Application 是一種架設在 Web 伺服器(Server)上,接受使用者資訊、處理並回傳網頁資訊的應用程式,基本的架構是 Client/Server,Server 只負責處理資料,並且和資料儲存區間溝通與交換資料,在處理完成後產生網頁指令,並輸出到用戶端。
初學者容易搞錯的地方: Web Application 因為以 Client/Server 為主,Server 只會負責資料交換與運算,但無法做狀態記憶,應用程式必須實作記憶狀態的方法。 |
用戶端(Client)是一種實作網路通訊的本機應用程式(Local Application)-大部份是瀏覽器,或是實作網路通訊用戶端的伺服器程式,負責處理/解譯由伺服器傳輸而來的網頁標記資料(tagged data),然後繪製(rendering)成一個完整的網頁畫面,並且處理存在標記資料中的指令程式碼(scripting language),讓用戶端具有快速處理與回應的能力。
初學者容易搞錯的地方: 用戶端指令碼只能使用在用戶端,對於使用者操作做即時回應處理,但它和伺服器端程式是完全不同的東西(就算使用的程式語言都一樣),所以除非實作特別的機制,否則不能夠直接呼叫。 |
Web Application 使用的標記資料是一種以標記(tag)定義各項資料的格式,藉以讓用戶端處理的資料流(stream),網頁使用的標記資料格式稱為 HTML,或者是使用更嚴謹的 XML 格式,裡面包含了文字資料,超連結或是加密的二進位資料(編碼為 Base64 格式的字串)等等。
ASP.NET 的簡介
早期 Web Application 都是由一種稱為 CGI(Common Gateway Interface)的小型程式所組成,在 Web 平台發展起來之前,CGI 多半是以處理表單(Form)資料為主,常見的 CGI 程式例如 Perl 或 C,所有的網頁格式都是由應用程式開發人員所設計,所以早期的網頁美工並不被重視,因為程式開發人員通常沒有美工底子。
但是在 Web 平台迅速發展,Web Application 日漸複雜之際,CGI 的開發特性已經逐漸不符需求,於是開始有一些簡化程式設計流程與提供強大資料處理能力的模組被研發出來,而且都形成 Web 伺服器的外掛模組(plug-in module),目前常見的 PHP/JSP 都是如此。
在 Microsoft 平台,IIS 1.0 開始,是以 ISAPI(Internet Server Application Programmable Interface)為基礎,讓 C/C++ 開發人員得以存取 IIS 的 HTTP 通道(tunnel),來開發自訂的應用程式。IIS 2.0 則以一個新的 ASP(Active Server Pages)模型,讓 VBScript/Jscript 開發人員得以發展 Web 應用程式,除了可以使用簡單的程式語言發展程式外,它的 COM 延伸性使得 ASP 的可擴充性大幅提升,讓 ASP 在 IIS 3.0-5.0(即 Windows NT 4.0 SP3-Windows 2000)時期盛極一時,成為 Web Application 發展的主流平台之一。
隨著 Microsoft 發展 .NET 策略之時,正是 ASP 平台紅極一時的時候,而他們也看出了 ASP 的許多限制(例如程式語言只支援 VBScript/Jscript、只能存取支援 COM 的元件,直譯式語言的效能問題等),因而著手重新設計 ASP 的架構,導入基礎類別庫(Base Class Library)的支援,強化了程式模型以及平台的支援,在 2002 年推出併含於 Microsoft .NET Framework 1.0 的 ASP.NET 1.0 版,宣告新一代的 ASP.NET 時代的開端,現在最新的版本是 ASP.NET 2.0,內含於 Microsoft .NET Framework 2.0。
ASP.NET 是一種架設在 IIS 上面的延伸模組(ISAPI Extension Module),提供簡化 Web Application 開發與處理資料的能力,並且具有可延展性的能力,讓 Web Application 可以存取 Server 的資源、當作用戶端或者是存取遠端資源等能力,這些都是 ASP 時代內建的能力所做不到的。
ASP.NET 基礎架構
前面有提及,ASP.NET 是一種 IIS 的延伸模組,它和其他 ISAPI 模組一樣,都會在 IIS 接收到第一個使用者連接到 IIS Request 時,載入對應的模組,並建立一個 Worker Process(應用程式的執行空間,IIS 6.0 以後的版本才會有)。
當應用程式要求進入 Worker Process 時,IIS 會搜尋 ISAPI 模組的對應表(網站的內容→主目錄→設定),決定要載入的 ISAPI 模組,若是 ASP.NET,則會載入 ASP.NET 的 ISAPI 模組(aspnet_isapi.dll),在載入 ASP.NET 模組時,會建立 ASP.NET 應用程式的執行空間(Hosting Environment 及 AppDomain),讀取應用程式的 Web.config,將應用程式的設定值讀入,然後套用 Global.asax 中的應用程式事件設定,然後開始處理 ASP.NET 事件模型:
在應用程式載入完成後,就開始處理要求的網頁事件與資料,而這個要求會視用戶端識別的不同而有所不同,對於 Web Server 和 ASP.NET 來說,每一個使用者的要求都是分開的,這樣可以確保每個使用者都是獨立的空間包含 Session 和 Cookie 都是如此。
但請特別注意,ASP.NET 本身也是 Client/Server 架構,除非在明確使用 Session 物件或其他方法(View State, Cookie, Query String 等)保存資料,否則伺服器是會丟棄這些資料的。
初學者容易搞錯的地方: ASP.NET 不會「主動」幫你記住任何東西(任何 Web Application 皆然)。 它和 Windows Form 應用程式不同,Windows Form 應用程式執行的地方是在同一台電腦與同一個使用者環境下,使用共用變數就可以記得狀態,但 ASP.NET 是在伺服器執行的程式,瀏覽器只是負責繪製出由伺服器傳來的 tagged data stream,變成一個網頁介面,連瀏覽器都不會知道狀態資料,這必須要由程式開發人員設計狀態保存機制,才能在 Web Application 中保存狀態資料。 |
ASP.NET 事件模型
在以往的 ASP 時代,程式碼是循序執行的(Sequence Execution),有寫過 ASP 程式的開發人員都明白,在 ASP 時代許多程式碼都和 HTML 碼混在一起,人稱「義大利麵」的程式模型,讓程式開發人員總是要在一堆程式碼中處理需要的動作,像是 Paged Data Grid,或是分開的畫面處理(如 Tab View)等。
在 ASP.NET,雖然程式已經改成 event-driven model(事件驅動式模型),但是它其實是把控制流程的 Request 指令變成一個一個的事件引動子(event-fire operator),這個未來我們會再談這個部份。
當 ASP.NET 載入頁面時,會依照下圖的流程處理,分為初始化階段(Initialize Phrase)、載入階段(Load Phrase)、繪製階段(Render Phrase):
ASP.NET 程式碼模型
ASP.NET 是採用程式碼與頁面分離式(Code-Behind Page)模型,以及程式碼與頁面混合式模型(Single-File Page,與 ASP 相同),程式開發人員可以選擇使用這二種模型之一,但在使用 Visual Studio(包括 Visual Studio Express)的時候,應該要使用 Code-Behind 模型,因為它具有下列的好處:
- 程式碼和頁面分離,讓美工與程式開發得以並行,或是由程式開發人員寫好程式時,由美工人員來設計頁面(但有時這個方法其實會造成一些困擾...),而美工人員也無法看到與修改程式碼。
- 程式碼可以編譯,並且部署時只需要部署編譯好的組件(Assembly),可保護程式碼。
- 編譯後的程式碼比直譯的程式碼要快,而 Single-File Page 每次都需要先行編譯才可以執行。
若程式碼要被多個頁面共用時,必須要放置在 App_Code 目錄之中,像是需要共用的程式碼(例如資料存取或運算)都可以放在這個目錄。
ASP.NET 在程式載入(第一次呼叫)時期,會動態產生頁面控制項的程式碼,和開發人員的程式碼合併編譯,形成一個 DLL 模組,再交由 ASP.NET 執行,也就是因為這個部份的新實作方法,使得以往在 ASP.NET 1.x 時可以使用的 Web Form 程式碼繼承功能無法再使用,也就是 ASP.NET 2.0 的 Web Form 程式碼是不可繼承的。
初學者容易搞錯的地方: ASP.NET 2.0 的頁面組件(Page Assembly)是不可繼承的,所有共用型的程式碼必須要放在 App_Code 資料夾中,才會被 ASP.NET Compilation Tool 編譯,或者也可以放在共用的類別庫中由頁面組件程式呼叫。 |
看到這裡,初學者應該會對 ASP.NET 應用程式架構有一個基本的認識,可以趁此時把原本的一些錯誤觀念都導正過來,順便可以消化一下這些知識,才可以繼續應付未來的知識。
ASP.NET 控制項模型,我們將於下回繼續說明,敬請期待。