快速搞懂 ASP.NET MVC

來源:互聯網
上載者:User

有一隻企鵝首先發現地球暖化、冰山在融化,回來告訴其它企鵝,卻沒有任一隻企鵝願意相信;因為企鵝們覺得現在生活過得很好,都不想費心思考如何改變、改變何時會來臨,因此仍每天做例行性的工作,不願去研究別人的觀點。「有時人們會抗拒改變,其實只是不想改變;但是願意接收新觀念的技術人員,通常會活得比較久」。本帖只提供 MVC Pattern 的觀念和架構介紹,僅供未接觸過 MVC Framework 的 .NET 技術人員作為參考之用,以評估是否要深入學習或在將來的項目匯入。

常在網路上,看到有網友誤認 MVC 和 3-Tier (三層架構) 是類似的東西:
http://topic.csdn.net/u/20090405/21/97a137ff-2105-4117-a0c3-39d7f0f1c952.html
http://topic.csdn.net/u/20090415/13/9ebe5011-c56b-47e6-9f89-40b70896a041.html

但二者本質上是完全不同的概念,如下:

3-Tier 或 N-Tier 的架構,中介層可能包含 EJB, Enterprise JavaBeans (J2EE),或 .NET Enterprise Services、Remoting、WCF:
Client (WebPage) -- [ BLL (商務邏輯層) -- DAL (資料訪問層) ] (Web Server) -- 資料來源或資料庫
Client (WebPage) -- [ BLL (商務邏輯層) -- DAL (資料訪問層) ] (Web Server + Application Server) -- 資料來源或資料庫

MVC 則為:
● Model (模型) - 包含 BLL、DAL。View 和 Controller 都依賴於 Model,但是 Model 既不依賴於 View,也不依賴於 Controller,這是分離的主要優點之一
● View (視圖) - 僅負責產生輸出 (UI)。以 ASP.NET MVC 來說,不再有 Code-behind 這種 .aspx.cs 檔案,亦無 runat="server" 標記、form 標記、控制項聲明、事件處理
● Controller (控制器) - 控制整個系統的 workflow、運作邏輯、錯誤處理、身分驗證和授權、使用者輸入資料驗證、…等等

總的來講,微軟的 ASP.NET MVC Framework 是為了讓 ASP.NET 更適合中、大型的項目,能統一規劃、控管整個網站系統的流程 (用 Controller 處理),並更有效地分工開發、日後維護 (避免許多 WebForm 裡重複出現相同功能的自訂函數)、管控某個功能在修改後對系統整體的影響,並將不同的功能作更明確地切割,讓不同專長的技術人員各司其職,也順便提高了代碼的可讀性,便於測試 (TDD, test -driven development) (減少直接綁到使用者介面中的代碼量) [4],並達到「鬆散耦合 (loosely coupled)」,讓組件易於更換和重複使用。但也因此,ASP.NET 程式員必須先改變過去,把很多商務邏輯、輸入驗證、頁面切換…等雜七雜八的功能,全部寫在 Code-Behind (aspx.cs) 裡的舊習慣。

ASP.NET MVC provides a framework that enables you to easily implement the model-view-controller (MVC) pattern for Web applications. This pattern lets you separate applications into loosely coupled, pluggable components for application design, processing logic, and display. ASP.NET MVC also greatly facilitates test -driven development (TDD).

事實上,MVC Pattern 的發明已有二十多年,其與再衍生的觀念和架構 (MVP),在 Java / J2EE / Struts 的一些 Framework 早已行之多年。MVC 模式的結構如下 [4]:

● View (JSP) 只純粹用來產生輸出,不涉及資料來源的訪問、事件處理、各種邏輯處理和運算工作。因此更適合大型項目的分工,把這層完全交由美工人員製作 (而非程式員兼美工和排版)。此層如同 ASP.NET 中的 .aspx 前台頁面,亦即 UI (User Interface)。

● Model (JavaBean、EJB 組件) 用來存放獨立且可重複使用的組件,包括:資料來源 (資料庫) 的訪問、商業邏輯的代碼,並應與 View 作完整地切割,以便保留系統日後擴充或改寫時的彈性。此層如同 ASP.NET 中的 App_Code 檔案夾中的自訂類、DataSet (.xsd)、TableAdapter、…等等。

● Controller (Java Servlet) 用來控制整個網站處理的「流程」,負責協調 View 和 Model 之間的流程傳遞和轉向,也要管理和指派由哪個檔案去接收使用者所提出的「請求 (request)」,亦即由它決定要展現哪一個 aspx 檔案給使用者。當使用者從瀏覽器送出 request 時 (例若用按一下滑鼠頁面中的控制項,或輸入資料後單擊 Button 的提交、輸入 URL 網址、點選 hyperlink…等等),Controller 裡定義的某些 method 會判斷要交由 Model 中的哪些運算邏輯去處理,然後再判斷要將處理結果傳回哪一個 View 去顯示出來。此外,Controller 還可包含錯誤處理、授權、輸入驗證…等功能的代碼,集中統一處理,以避免傳統 WebForm 裡大量重複的代碼。但說穿了,Controller 事實上只是一個自訂類,搭配一些 Attribute (特性)。而 Controller 也是目前 ASP.NET 所欠缺的部分。

 


圖 1 MVC (Model 2) 架構的運作方式,可與 2 的 ASP.NET MVC 項目相互對應

事實上,在 Java / JSP / JavaEE 常引用的網站開發架構中,還可分為 Model 1 與 Model 2。而 Model 1 還可分為二至三種,如下:

● 第一種是將 HTML 和 .NET (Java) code 混在一起,俗稱意大利麵的寫法,如:古早的 ASP。這種 Inline code 最為人垢病的問題,是代碼的可讀性低、難以維護。

● 第二種是由與 .aspx 一對一搭配的 Code-Behind code (.aspx.cs) 直接存取資料庫,亦即二層式的架構。但這樣的缺點是代碼難以重複使用,而且因為邏輯已寫死在固定的頁面裡,會造成系統日後擴充、維護的困難。

● 第三種是經由自訂類庫、App_Code 檔案夾中的自訂類或組件,去訪問資料庫,或做商業邏輯的運算 (JSP + JavaBean)。但此種做法仍缺乏「流程 (flow)」的統一控管,導致每一支 ASPX (JSP) 都要驗證使用者身份、驗證 request 的參數、處理 Session、做例外處理,甚至包括 View 裡的寫碼原則、語系設定,都得在每一支 ASPX 對應的 Code-Behind 去處理,也因此不適合大型系統的開發、擴充和維護。這種架構雖然也能做到虛擬式的三層式或多層式架構,但也是目前 ASP.NET 的極限。

至於 Model 2,即俗稱的 MVC Pattern,則加入了 Controller 的部分,將流程及事件交由中心控管,除了可讓整個系統的運作流程更為明確,有效切開各層的工作,亦可避免讓 View 裡的 Code-Behind 去處理 Model 中的資料庫訪問、商業邏輯運算,也不必再每個頁面重複撰寫「流程傳遞和轉向」的代碼,而改由中央的 Controller 程式碼 (action method) 來統一控管。

但 MVC 架構也有其缺點,例如開發人員需要另外花時間轉換觀念及學習某一個 Framework,尤其是 .NET 的開發人員,因為過去較沒有 Controller 統一協調流程的觀念,勢必得重新習慣,將很多原本寫死在各個頁面中的代碼,統一改寫在 Controller 裡面。而且系統在設計階段時,即要先協調好各個類及對象,彼此間資料交換的格式及做法,因此勢必得拉長系統事先的分析、規劃時程。但若能有像 Java Struts 或 ASP.NET MVC Framework 這樣現成的架構可套用,則日後開發大型系統時,即可望達到事半功倍的效果。

要開發 ASP.NET MVC,必須要有 Visual Studio 2008 + SP1,並下載 MVC 套件 (經過至少兩年的研發,微軟終於在 2009 年 4 月發布了 1.0 正式版),下載網址如下:
ASP.NET MVC 1.0 download (2009/04/09):
http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&displaylang=en

安裝完成後,在建立項目時,會多出一個「ASP.NET MVC Web Application」的選項。建立一個預設的 MVC 項目後,其在 VS 解決方案的結構如所示:


圖 2 View 中的 ASPX、ASCX、MasterPage 純粹負責顯示用,預設沒有配置 Code-Behind 檔案 (aspx.cs)

如 2,ASP.NET MVC 項目,會自動產生儲存 MVC 檔案的三個檔案夾、控制流程程的兩個 Controller 類、多個沒有 Code-Behind 的 View 頁面,和定義 Routing rules 的 Global.asax.cs。

事實上版工我在一年前試玩 ASP.NET MVC Beta 版時,當時的 View 預設仍配有 Code-Behind 檔案,但裡面空無一物,只有一行注釋:
!-- Please do not delete this file. It is used to ensure that ASP.NET MVC is activated by IIS when a user makes a "/" request to the server. --

在前陣子發布的正式版裡,View 預設已不配置 Code-Behind 檔案。此外,ASP.NET MVC 裡的 View,為了讓項目開發更明確地切割,已不再有頁面初始化和載入方法,也沒有事件處理常式,除了基類聲明以外沒有任何內容,基類聲明為 System.Web.Mvc.ViewPage,而不再是過去 WebForm 的 System.Web.UI.Page。

新創的 ASP.NET MVC 項目,直接按 F5 即可執行,如 3 所示。但由於 MVC 的 View 會在顯示前先要求 Controller 運行 (參考圖 1),因此若您嘗試將 View 裡的某個 .aspx 設為「起始頁」後,按 F5 執行時,反而會發生「HTTP 404. The resource cannot be found.」的錯誤,亦即若想直接導航至該頁面將不起作用。


圖 3 ASP.NET MVC 項目的首頁

您會發現瀏覽器裡的 URL 會像下面這樣,網址不是具體的 .aspx 副檔名:

http://localhost:連接埠號碼/Home/index
http://localhost:連接埠號碼

事實上該頁的內容,是去捉 Views/Home 檔案夾底下,的 Index.aspx 的內容來呈現。其由 Global.asax.cs 配置,並用了「URL 重寫 (Url Routing)」,讓使用者可以按你自己定義的的規則來訪問網站 [14]。

在圖 3 首頁的右側,會有兩個 hyperlink,可分別導向「LogOn.aspx」、「About.aspx」頁面;但 hyperlink 要導向哪一個頁面,不是寫死在 View 的頁面中 (已無 Code-Behind),而是統一由 Global.asax.cs 去定義 Routing rules,去解析當瀏覽器收到 URL、表單或任何 request 時,應該要扔給哪一個 Controller 自訂類去處理;再由該個被指定的 Controller (如 2 裡預設自動產生的 HomeController.cs),裡面所定義的一或多個 System.Web.Mvc.ActionResult 類,以及 View 方法 (術語叫 action method),去設定要把 UI render 回哪一個 View (頁面) 去,也就是本文一開始所提到的 (參考本帖圖 1),Model 2 架構是由 Controller 檔案,去統一控管整個 ASP.NET 系統的流程、頁面導向,而不是寫死在各個 aspx.cs 檔案裡。

以下為 Global.asax.cs 的一部分代碼,網友們可搭配參考 2 裡 Controller、View 的結構去閱讀:

using System.Web.Mvc;
using System.Web.Routing;

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // C# 3.0 的「匿名型別 (Anonymous Type)」文法
        routes.MapRoute(
            "Default",                      // Route name
            "{controller}/{action}/{id}",   // URL with parameters (控制器名 / 操作名稱 / ID 參數)
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );
    }
}

 

MapRoute 方法裡的三個參數,分別代表:routes、route name、URL。其中第一個參數 "Default",代表了項目中的 Default.aspx (不是位於 View 檔案夾裡)。這個 URL Routing 是為瞭解決使用者直接存取網域名稱時,會出現找不到檔案的情形,所以要採用這個方法,將首頁改成 Routing 到 Home/Index 上。因此當您在瀏覽器的地址欄輸入:

http://localhost:連接埠號碼/Default.aspx

http://localhost:連接埠號碼

亦會導至圖 2 中的 Views/Home/Index.aspx。

System.Web.Mvc Namespace (MSDN Library, 暫無中文版):
http://msdn.microsoft.com/en-us/library/system.web.mvc.aspx

RouteCollectionExtensions.MapRoute Method:
http://msdn.microsoft.com/en-us/library/dd470521.aspx

ASP.NET MVC Framework (Part 1) (ScottGu 於 2007 年 11 月發表的 blog,圖中為 ASP.NET MVC 在 Beta 版時的畫面):
http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx

在圖 3 的首頁裡,當滑鼠移到右側的 hyperlink 時,實際連結的頁面名稱 (某個 .aspx) 並不會直接顯示在瀏覽器的地址欄、瀏覽器下方的資訊列裡,因為 request「轉向」的運作皆統一由 Controller 處理,亦即由圖 2 中 HomeController.cs 裡,配置的 System.Web.Mvc.ActionResult 類的 actionName 去指定,因此瀏覽器的網址仍會維持 Site.Master (MasterPage) 裡的 Html.ActionLink 綁定,所配置的 actionName (即下方兩行代碼的第二個參數 "Index"、"About"),而不會如過去 ASP.NET 1.x / 2.0 般,直接在地址欄裡,顯示某一個 .aspx 的頁面名稱。

以下為 Site.master 的一部分代碼:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<ul id="menu"> 
    <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
    <li><%= Html.ActionLink("About", "About", "Home")%></li>
</ul>

 

Controller 除了用來控管整個網站的流程轉向外,事實上還能避免大量的代碼重複,亦即統一處理一些系統可「共用」的功能,例如:驗證使用者身份、輸入驗證 (validate)、Session 管理,或是像購物網站中,當購物車裡物品的添加、修改、移除時,任何使用者皆相同的「共通邏輯」處理;以及要結帳時,去做購物數量、單價相乘的計算動作,或將某個儲存購物明細的 Collection 資料結構對象加入 Session,最後再轉向某一個頁面 (View)。

 

總結:

本帖僅是給 .NET 技術人員,作為初步瞭解 MVC Pattern,以及 ASP.NET MVC Framework 的入門文章。若有興趣深入研究的網友,可參考本帖最下方的「相關檔案」,另部落格園及網路上已有許多相關的文章。至於通用的 MVC 觀念,亦可參考坊間 JSP / Struts / J2EE 的網路論壇、相關書籍,或 Design Patterns (設計模式) 中的「複合模式 (Compound Pattern)」[15]。

如同 MSDN Magazine 中提到的 [7],ASP.NET MVC 不是用來取代傳統 ASP.NET WebForm 的,兩者有各自的優點和缺點,而將來的 ASP.NET MVC 還可能在 UI、控制項拖曳、Routing 上持續改進。不過身為一個技術人員,最好能早點釐清兩者的特性與優缺點 [4] [6],以評估是否要深入學習,或在將來的項目匯入;並思考為什麼微軟要推出這個架構,且還花了至少兩年的時間很謹慎地去研發。

 

--------------------------------------------------------

相關檔案:

[1] MVC : The Official Microsoft ASP.NET Site:
http://www.asp.net/mvc/
http://www.asp.net/learn/mvc/
http://www.asp.net/learn/mvc/tutorial-01-cs.aspx
http://www.asp.net/learn/mvc/tutorial-02-cs.aspx
http://www.asp.net/learn/mvc/tutorial-03-cs.aspx

http://www.asp.net/learn/mvc/tutorial-38-cs.aspx
http://www.asp.net/learn/mvc-videos/
http://forums.asp.net/1146.aspx

[2] ASP.NET - Home:
http://aspnet.codeplex.com/Wiki/View.aspx?title=MVC

[3] ScottGu's Blog (美國微軟開發部門總經理):
http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx

[4] Model-View-Controller (MSDN):
http://msdn.microsoft.com/en-us/library/ms978748.aspx (英文)
http://msdn.microsoft.com/zh-cn/library/ms978748.aspx (中文)

[5] Page Controller (MSDN):
http://msdn.microsoft.com/en-us/library/ms978764.aspx
http://msdn.microsoft.com/zh-cn/library/ms978764.aspx

[6] Implementing Model-View-Controller in ASP.NET (MSDN):
http://msdn.microsoft.com/en-us/library/ms998540.aspx
http://msdn.microsoft.com/zh-cn/library/ms998540.aspx

[7] Building Web Apps without Web Forms (MSDN Magazine):
http://msdn.microsoft.com/en-us/magazine/cc337884.aspx
http://msdn.microsoft.com/zh-cn/magazine/cc337884.aspx

[8] 從零開始學習 ASP.NET MVC 1.0 (一) 開天闢地入門篇 (子秋的部落格):
http://www.cnblogs.com/zhangziqiu/archive/2009/02/27/ASPNET-MVC-1.html

[9] ASP.NET MVC Framework 與 WCSF 中 MVP 模式之小小比較 (Terry Lee):
http://www.cnblogs.com/Terrylee/archive/2008/01/01/aspnet-mvc-framework-vs-wcsf-mvp.html
ASP.NET MVC Framework 體驗(1):從一個簡單一實例開始 (Terrylee):
http://www.cnblogs.com/Terrylee/archive/2007/12/11/aspnet-mvc-framework-overview.html

[10] 部落格園 ASP.NET MVC 技術專題:
http://kb.cnblogs.com/zt/mvc/

[11] 一步一步學習 ASP.NET MVC 1.0 建立 NerdDinner 範常式序:
http://blog.entlib.com/entlibforum/archive/2009/03/28/asp.net-mvc-1.0nerddinner-part-1.aspx

[12] ASP.NET MVC 開發心得分享 (1):開發流程篇 (繁體中文):
http://blog.miniasp.com/post/2009/01/ASPNET-MVC-Developer-Note-Part-1.aspx
ASP.NET MVC 開發心得分享 (2):與原始碼共舞 (繁體中文):
http://blog.miniasp.com/post/2009/02/ASPNET-MVC-Developer-Note-Part-2.aspx
研究 Oxite 這套 CMS 系統吧!(繁體中文):
http://blog.miniasp.com/post/2008/12/Microsoft-Open-Source-content-management-system-Oxite-using-ASPNET-MVC.aspx

[13] .NET Framework Class Library:
System.Web.Mvc Namespace (暫無中文版):
http://msdn.microsoft.com/en-us/library/system.web.mvc.aspx

[14] URL Routing:
http://blog.csdn.net/chsword/archive/2008/03/11/2165866.aspx
http://www.cnblogs.com/terrylee/archive/2007/12/16/aspnet-mvc-framework-url-routing.html
http://www.cnblogs.com/qleelulu/archive/2008/03/17/1109893.html

--------------------------------------------------------

相關書籍:

[15] Head First 設計模式, Chapter 12:
http://www.dearbook.com.cn/book/213719
http://www.china-pub.com/36020

[16] Free ASP.NET MVC eBook Tutorial:
http://weblogs.asp.net/scottgu/archive/2009/03/10/free-asp-net-mvc-ebook-tutorial.aspx

[17] ASP.NET MVC in Action:
http://www.manning.com/palermo/

[18] Pro ASP.NET MVC Framework:
http://www.apress.com/book/view/1430210079

[19] Professional ASP.NET MVC 1.0:
http://www.wrox.com/WileyCDA/WroxTitle/Professional-ASP-NET-MVC-1-0.productCd-0470384611.html

--------------------------------------------------------

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.