加入RUN!PC粉絲團
最近新增的精選文章
 
最多人點閱的精選文章
 
 
精選文章 - 開發技術
分享到Plurk
分享到FaceBook
 
新一代 .NET Framework 4.0的4大主軸(3)
MVC 2為大型開發案奠定基礎
文/董大偉

面對日漸龐雜的資訊應用需求,以及全球化競爭下的挑戰,台灣在兩岸三地之間特有的整合需求與技術議題中,如何讓軟體開發專案架構更具彈性,以利後續的維護、自動化測試與TDD(Test-driven Development)機制的導入,逐漸成為軟體產業提昇的發展方向之一。

最新推出的ASP.NET 4.0中,MVC已然併入並成為ASP.NET新功能中一個相當重要的部分,但是,ASP.NET MVC卻很容易讓.NET的Web Forms開發人員困惑。主要是來自MVC Pattern並非微軟最先提出,在開發工具領域也不是率先支持者,傳統的ASP.NET Web Forms技術更是與MVC水火不容。

因此就Web開發工具的演進來看,JSP、PHP、甚至ASP都曾經有支援MVC Pattern的套件和產品問世,從設計的架構來看,在2002年所誕生的ASP.NET卻是看不出打算支援的計劃。然而為何在近10年後的今天,微軟卻要推ASP.NET MVC Framework?即使犧牲ASP.NET Web Forms中所有的控制項支援也在所不惜?
何謂MVC?
在討論ASP.NET MVC 2之前,必須要先明白為何需要MVC Framework。可能多數讀者已經知道MVC是一種Pattern,MVC這3個縮寫字母分別代表了Model-View-Controller這3個層面的程式碼;或者MVC這個Pattern要求我們在開發時,把需要程式碼達成的一個功能,切割成Model、View、Controller這3個部份的程式碼,這使得一個簡單的功能,在撰寫的時候比傳統的ASP.NET Web Forms來的複雜許多。

View是一個.aspx頁面,你會發現MVC應用程式當中的ViewPage上,沒有任何的asp.net控制項,取而代之的是傳統的HTML Code,或是透過In-Line Command(或稱作Code nugget)方式被包裹在<% ... %>當中執行的程式碼。

有點回到過去ASP時代那種時空錯置的感覺,但確實是如此。ViewPage上可以有各種程式碼,主要的功能就是呈現(Render HTML)頁面,或是接收從Controller傳遞過來的參數(ViewData)。

而輸入方塊InputBox也是透過類似「Html.TextBox(…)」這樣的指令碼產生,這些動作都在宣告一件事情,ViewPage(前端頁面)是完全獨立!並沒有所謂的Code Behind、WebControls,諸如此類過去你熟悉的Web Forms功能與支援,但是卻擁有ASP.NET Web Forms所沒有的程式碼獨立性。

在這樣的架構底下,當你按下Submit鈕把頁面POST回去之後,也並非由網址列所指向的.aspx頁面來處理,取而代之的是Controller,一個繼承於BmiController類別的物件。

我們透過這個Controller類別接收由ViewPage傳遞過來的參數,或是將運算後的結果回傳給ViewPage。而Model最典型的情境,則可用於當運算的結果需要與後端資料庫互動時,所建構出來的Data Model,如圖1的架構。

圖1:Model最典型的應用情境。



MVC架構
整個程式的進入點,從.aspx頁面轉變成Controller類別,由Controller第一線面對用戶端的需求,決定如何進行邏輯運算,選擇如何呈現頁面,或是調用哪些Model進行資料處理。然而不管怎麼運作,M-V-C三塊依舊是清楚界限分明且相當獨立,與過去ASP.NET程式碼中.aspx頁面與程式運作邏輯密不可分的狀況截然不同,而整個專案架構也因此會有不同的變化。

以實際例子來看,要完成一個如圖2中的BMI運算,在撰寫時切割成可呈現在用戶端的[/Views/Bmi/Index.aspx];負責第一線面對用戶需求的[Controllers/BmiConroller.cs];實際負責運算的BMI.cs類別。

圖2:BMI運算。


之所以要盡可能把程式碼切割成不同部分,主要是希望能夠降低程式碼彼此之間的相依性,讓每一個模塊都可以各自獨立開發、進行Unit Test、提高日後的重用性。一般傳統ASP.NET Web Forms開發人員,或許已習慣於透過IDE開發Web應用程式,時常會「不小心」把應分開成多個類別的程式碼,寫在一個Button的Click事件當中,進行資料庫連線、撈資料,之後還直接撰寫程式碼處理完成的資料,接著又將資料Bind到UI控制項上。

儘管這樣寫似乎很直覺很快,卻讓整個應用程式的架構蕩然無存,本來我們希望切割開來的Model-View-Controller三塊程式碼,卻被開發人員寫在一起,緊密得毫無切割的可能,造成程式碼之間的相依性過高。

相對的,未來的重用性就會大幅的降低,也讓單元測試的難度大為提高。而且,這樣的程式碼撰寫方式,同一個開發人員要擅長各種不同領域的技術,一個ASP.NET開發人員,要同時熟悉HTML、CSS、JavaScript、SQL、VB或C#等,才能夠完成一個可上線的程式。

從這樣的角度你會發現,越是在大型的Web應用程式開發案時,越需要MVC這樣的架構。但是不可諱言,這樣的開發方式進入障礙相對也不少,過去ASP.NET應用程式的開發相當直覺,習慣於Web Forms的開發人員,一時之間要進入MVC世界,所需面對的挑戰和開發方式的改變,確實是令人感到有些難以招架。也因此從ASP.NET MVC的Preview版本,一路上增加了不少功能協助。


讓開發更便利的擴充
演變至今的新版ASP.NET MVC 2又包含了哪些新功能呢?諸如Strongly Typed Helpers,配合新一代Visual Studio 2010平台,即可幫助開發人員在撰寫ViewPage時,針對Model中的特定資料表,可以享有如同在使用Entity Framework時的IntelliSense支援。

如圖3的ViewPage程式碼,在建立Label、TextBox、Validation時,使用到了Model(Customer資料表)中的CustomerID欄位,呈現出來的效果。

圖3:Model中的特定資料表可支援IntelliSense。


更有趣的是,當我們在Data Model中針對資料欄位加上的DisplayName這個修飾字之後,你會發現呈現出的欄位立即變成支援我們填入的欄位名稱,如圖4。也就是說,ViewPage上的Html Helper,不僅開始支援IntelliSense,也支援Model中的Metadata,這些功能將大幅提昇MVC應用程式開發速度。

圖4:ViewPage上的Html Helper也支援Model中的Metadata。


不僅如此,在2.0版的MVC中,除了前面看到的Label之外,包含Validation也在支持的行列中。甚至,你可以直接在ViewPage寫上:「<%: Html.EditorForModel() %>」,即可直接配合Model動態產生該頁面的編輯欄位,相關的資料也會截取Model的MetaData,而自動呈現出你需要維護的欄位,如同DynamicData中使用到的DataAnnotation技術一般,既方便卻又維持著彼此之間的獨立性。(圖5)

圖5:截取Model的MetaData後自動呈現出欄位。


這一個概念相當重要,這讓MVC應用程式的開發較接近過去撰寫Web Forms使用DetailsView的效果,卻不至於把View和Model綁在一起,形成相依。也就是說,這個ViewPage並非僅針對某一個固定的Table Schema,而是可用於(配合)後端各種不同的Model。

別忘了這部分的支援還包含RangeAttribute、RequiredAttribute、StringLengthAttribute、RegexAttribute等修飾字,這讓MVC ViewPage的設計輕鬆不少,同時也汲取DataAnnotation的優點,讓Model來決定前端的呈現方式。如此一來,就可以建立出與後端Data Model無關的前端View頁面,讓程式的開發架構更加的有彈性。


程式碼安全性提昇
另外,之前我們撰寫的ViewPage當中用到了「<%: … %>」,與過去常用的「<%= … %>」有所不同。這是因為在透過<%= … %>撰寫程式時,需要特別注意輸出的資料是否為JavaScript,例如當開發人員透過「<%=ViewData["UserInputTextBox"] %>」輸出資料時,倘若UserInputTextBox是來自使用者輸入的欄位。

而開發人員卻又忘記針對資料進行Html Encoded,很可能會讓駭客有機會透過Cross Site Scripting方式進行攻擊,在輸入欄位中放入JavaScript,使頁面在用戶不知覺的情況下導入其他網站,造成資料外洩或其他更大的損失。

對上述問題積極的做法是在ASP.NET 4.0加入<%: … %>指令碼,可自動將輸出字串進行HtmlEncode動作,如此一來可省去開發人員撰寫程式碼上的時間,亦可確保不致於因為一時的疏忽導致安全上的疑慮。


AsyncController與Areas
可以利用非同步方式來呼叫並處理長時間執行運算的AsyncController,同樣也是MVC 2的新成員,將有助於執行效能的提昇。透過這樣的機制我們可以讓需要長時間執行的服務(例如資料截取、大量運算、網路存取),以非同步的方式來執行,又不至於造成系統的過度負擔。

新增加的Areas,主要是用來幫助開發人員妥善的組織大型專案,如圖6。你會發現整個Area就包含了自己的Controllers、Views、Models,可以在Area的AreaRegistration.cs檔案中指定Url Route註冊方式。

圖6:在MVC專案增加一個Area。


這邊決定了該Area如何回應用戶端的呼叫,在過去沒有Area的MVC 1.0時代,如果專案相當龐大時,View資料夾下的ViewPage頁面可能相當多而複雜,相對的Controllers也會較為紊亂。如今在MVC2當中,你則可以針對需要的功能分類,建立不同的區塊(例如Admin、User、Portal等),以MVC架構撰寫程式碼,對於大型專案的切割和管理有相當大的幫助。


結語
面對大型且複雜的Web開發專案,你已經可以開始採用Visual Studio 2010配合ASP.NET MVC 2,當專案團隊跨過初期的進入門檻,後續的成果相較於Web Forms將相當令人期待。