侯永剛
摘要:MVC是一種軟件架構(gòu)的思想,該設(shè)計(jì)模式目前在很多領(lǐng)域都有著廣泛的應(yīng)用前景,2009年,ASP.NET MVC1.0正式版上市,到目前已發(fā)展到了MVC5。ASP.NET MVC非常強(qiáng)調(diào)“關(guān)注點(diǎn)分離”的概念,而且從開(kāi)發(fā)上來(lái)看就很容易讓開(kāi)發(fā)人員做到“關(guān)注點(diǎn)分離”,這個(gè)優(yōu)勢(shì)是Web Form完全無(wú)法匹敵的。本文簡(jiǎn)要闡述了ASP.NET MVC設(shè)計(jì)模式的概念,基本思想及其應(yīng)用。
關(guān)鍵詞:設(shè)計(jì)模式;ASP.NET MVC;MVC;控制器;視圖
一、MVC設(shè)計(jì)模式概述
MVC不是一種程序語(yǔ)言,嚴(yán)格說(shuō)起來(lái)也不算是個(gè)技術(shù),而是開(kāi)發(fā)時(shí)所使用的一種“架構(gòu)(框架)”。它就像是一種開(kāi)發(fā)觀念,或是一個(gè)存在已久的設(shè)計(jì)模式。
MVC最早是在1979年由Trygve Reenskaug所提出,并且應(yīng)用于當(dāng)時(shí)火紅的Smalltalk程序語(yǔ)言中。之所以會(huì)提出MVC的概念,主要目的就在于簡(jiǎn)化軟件開(kāi)發(fā)的復(fù)雜度,以一種概念簡(jiǎn)單卻又權(quán)責(zé)分明的架構(gòu),貫穿整個(gè)軟件開(kāi)發(fā)流程,通過(guò)“商業(yè)邏輯層”與“數(shù)據(jù)表現(xiàn)層”的切割,讓這兩部分的信息切割開(kāi)來(lái),用以撰寫(xiě)出更模塊化、可維護(hù)性高的程序代碼。
MVC是一種軟件架構(gòu)的思想,將一個(gè)軟件按照模型、視圖、控制器進(jìn)行劃分。其中,模型用來(lái)封裝業(yè)務(wù)邏輯,視圖用來(lái)實(shí)現(xiàn)表示邏輯,控制器用來(lái)協(xié)調(diào)模型與視圖(視圖要通過(guò)控制器來(lái)調(diào)用模型,模型返回的處理結(jié)果也要先交給控制器,由控制器來(lái)選擇合適的視圖來(lái)顯示處理結(jié)果)。
模型:負(fù)責(zé)定義信息格式與信息訪(fǎng)問(wèn)的界面,包括商業(yè)邏輯與信息驗(yàn)證。
視圖:負(fù)責(zé)用戶(hù)界面(UI)相關(guān)呈現(xiàn),包括輸入與輸出。
控制器:負(fù)責(zé)控制系統(tǒng)運(yùn)行的流程、跟瀏覽器如何交互、決定網(wǎng)頁(yè)操作的流程與動(dòng)線(xiàn)、響應(yīng)客戶(hù)端的各種要求、錯(cuò)誤處理。
二、初探ASP.NET MVC
ASP.NET WebForm時(shí),常用的開(kāi)發(fā)模式也將整個(gè)應(yīng)用程序分解為三個(gè)層次分別是表示層、事務(wù)層、數(shù)據(jù)訪(fǎng)問(wèn)層,那么ASP.NET MVC的三層與原三層架構(gòu)的關(guān)系是什么呢?
ASP.NET MVC僅僅是對(duì)原三層架構(gòu)中的表示層進(jìn)行解耦,主要實(shí)現(xiàn)HTML與C#代碼的分離。因此,其三層的功能主要如下:
View:視圖層,負(fù)責(zé)所有呈現(xiàn)在用戶(hù)面前的東西,最簡(jiǎn)單的說(shuō)法就是輸出與輸入。輸出工作就是呈現(xiàn)在瀏覽器上的界面,例如HTMl等;輸入工作就是將用戶(hù)輸入的數(shù)據(jù)傳回服務(wù)器,例如,在瀏覽器上呈現(xiàn)表單讓用戶(hù)輸入。
Model:模型,負(fù)責(zé)定義信息格式,對(duì)應(yīng)應(yīng)用狀態(tài)和業(yè)務(wù)功能的封裝,可以將它理解為同時(shí)包含數(shù)據(jù)和行為的領(lǐng)域模型(Domain Model)。Model接受Controller的請(qǐng)求并完成相應(yīng)的業(yè)務(wù)處理。
Controller:控制器,接收用戶(hù)的請(qǐng)求、決定呈現(xiàn)哪個(gè)View(視圖)、接收用戶(hù)輸入的數(shù)據(jù)。
1.控制器
MVC模式中的控制器(Controller)主要負(fù)責(zé)響應(yīng)用戶(hù)的輸入,并且在響應(yīng)時(shí)修改模型(Model)。通過(guò)這種方式,MVC模式中的控制器主要關(guān)注的是應(yīng)用程序流、輸入數(shù)據(jù)的處理,以及對(duì)相關(guān)視圖(View)輸出數(shù)據(jù)的提供。
過(guò)去的Web服務(wù)器支持訪(fǎng)問(wèn)以靜態(tài)文件存儲(chǔ)在磁盤(pán)上的HTML頁(yè)面。隨著動(dòng)態(tài)網(wǎng)頁(yè)的盛行,Web服務(wù)器也支持由存儲(chǔ)在服務(wù)器上的動(dòng)態(tài)腳本生成的HTML頁(yè)面。MVC則略不同。URL首先告知路由機(jī)制去實(shí)例化哪個(gè)控制器,調(diào)用哪個(gè)操作方法,并為該方法提供需要的參數(shù)。然后控制器的方法決定使用哪個(gè)視圖,并對(duì)該視圖進(jìn)行渲染。
URL并不與存儲(chǔ)在Web服務(wù)器磁盤(pán)上的文件有直接對(duì)應(yīng)關(guān)系,而是與控制器類(lèi)的方法有關(guān)。ASP.NET MVC對(duì)MVC模式中的前端控制器進(jìn)行了改進(jìn),路由子系統(tǒng)在前面,之后才是控制器。
理解MVC模式在Web場(chǎng)景中工作原理的簡(jiǎn)單方法就是記?。篗VC提供的是方法調(diào)用結(jié)果,而不是動(dòng)態(tài)生成(又名腳本)頁(yè)面。
2.模型
模型這個(gè)詞在軟件開(kāi)發(fā)領(lǐng)域被多次引用,代表數(shù)百種不同的概念,如成熟度模型、設(shè)計(jì)模型、威脅模型和進(jìn)程模型等。很少有開(kāi)發(fā)會(huì)議會(huì)自始自終都不談一兩種模型的。即便把“模型”這個(gè)術(shù)語(yǔ)的范圍限定在MVC設(shè)計(jì)模式的上下文中,也仍然可以探討面向業(yè)務(wù)的模型對(duì)象和面向視圖的模型對(duì)象哪個(gè)更具有優(yōu)勢(shì)。
ASP.NET MVC中討論的是那些發(fā)送信息到數(shù)據(jù)庫(kù),執(zhí)行業(yè)務(wù)計(jì)算并在視圖中渲染的模型對(duì)象。換句話(huà)說(shuō),這些對(duì)象代表著應(yīng)用程序關(guān)注的域,模型就是要顯示、保存、更新和刪除的對(duì)象。
為了僅使用模型對(duì)象的定義就能構(gòu)建出應(yīng)用程序特性,ASP.NET MVC5提供了許多工具和特性?,F(xiàn)在就應(yīng)該坐下來(lái)好好想一想要解決的問(wèn)題,然后為了呈現(xiàn)涉及的主要對(duì)象,就要編寫(xiě)一些簡(jiǎn)單的C#類(lèi)。準(zhǔn)備好了上面的工作,接下來(lái)就可以使用MVC提供的工具來(lái)為每個(gè)模型對(duì)象的標(biāo)準(zhǔn)索引、創(chuàng)建、編輯和刪除功能構(gòu)建控制器和視圖。
3.視圖
開(kāi)發(fā)人員之所以花費(fèi)大量的時(shí)間來(lái)重點(diǎn)設(shè)計(jì)控制器和模型對(duì)象,是因?yàn)樵谶@些領(lǐng)域中,精心編寫(xiě)的整潔代碼是開(kāi)發(fā)一個(gè)可維護(hù)Web應(yīng)用程序的基礎(chǔ)。
但是當(dāng)用戶(hù)在瀏覽器中訪(fǎng)問(wèn)Web應(yīng)用程序時(shí),這些工作他們是看不到的。用戶(hù)對(duì)應(yīng)程序的第一印象,以及與應(yīng)用程序的整個(gè)交互過(guò)程都是從視圖開(kāi)始的。
視圖實(shí)際上就是應(yīng)用程序的“大使”。顯而易見(jiàn),如果應(yīng)用程序的其他部分存在錯(cuò)誤,那么設(shè)計(jì)再好,再?zèng)]有瑕疵的視圖也不能彌補(bǔ)這方面的不足。同樣,如果創(chuàng)建一個(gè)丑陋且難以利用的視圖,那么許多用戶(hù)將不會(huì)給應(yīng)用程序提供證明它的功能多么強(qiáng)大、運(yùn)行多么順暢的機(jī)會(huì)。
控制器可以返回輸出字符串到瀏覽器。但在一些重大的Web應(yīng)用程序中,大部分的控制器操作需要以HTML格式動(dòng)態(tài)顯示信息。如果控制器操作僅僅返回字符串,那么就需要有大量的字符串替換操作,這樣就會(huì)變得混亂不堪。因此,模板系統(tǒng)的需要越來(lái)越清晰,此時(shí),視圖應(yīng)運(yùn)而生。
視圖的職責(zé)是向用戶(hù)提供界面。當(dāng)控制器針對(duì)被請(qǐng)求的URL執(zhí)行完合適的邏輯后,就將要顯示的內(nèi)容委托給視圖。
不像基于文件的Web框架,比如ASP.NET Web Forms和PHP,視圖本身不會(huì)被直接訪(fǎng)問(wèn),瀏覽器不能直接指向一個(gè)視圖并渲染它。相反,視圖總是被控制器渲染,因?yàn)榭刂破鳛樗峁┝艘秩镜臄?shù)據(jù)。
在一些簡(jiǎn)單的情況中,視圖不需要或需要很少控制器提供的信息。更常見(jiàn)的情況則是控制器需要向視圖提供一些信息,所以它會(huì)傳遞一個(gè)數(shù)據(jù)轉(zhuǎn)移對(duì)象,叫做模型。視圖將這個(gè)模型轉(zhuǎn)換為一種適合顯示給用戶(hù)的格式。在ASP.NET MVC中,完成這一過(guò)程由兩部分操作,其中一個(gè)是檢查由控制器提交的模型對(duì)象,另一個(gè)是將其內(nèi)容轉(zhuǎn)換為HTML格式。
三、 ASP.NET MVC的開(kāi)發(fā)觀念
在MVC模式的開(kāi)發(fā)中,應(yīng)該具有正確的開(kāi)發(fā)觀念,強(qiáng)大的工具若沒(méi)有正確的觀念支持,就像是給你一臺(tái)馬力強(qiáng)又省油的手動(dòng)檔汽車(chē),而你卻不知道離合器該如何正確使用,也許在開(kāi)了一段時(shí)間之后,覺(jué)得車(chē)子還是開(kāi)不快。
1.常見(jiàn)的問(wèn)題有以下幾點(diǎn)
1)把Model理解成實(shí)體類(lèi)(Entity)
在MVC中Model應(yīng)該包含兩部分功能,一部分是處理業(yè)務(wù)邏輯,一部分是提供View顯示的數(shù)據(jù)。
它應(yīng)該是業(yè)務(wù)邏輯真正的實(shí)現(xiàn)層。所以Model實(shí)際上是Bussiness Model(業(yè)務(wù)模型)。而Controller僅僅起一個(gè)“橋梁”作用,它負(fù)責(zé)把View的請(qǐng)求轉(zhuǎn)發(fā)給Model,再負(fù)責(zé)把Model處理結(jié)束的消息通知View。Controller的存在是為了使UI界面、UI邏輯、業(yè)務(wù)邏輯之間分離。
2)大量業(yè)務(wù)邏輯代碼堆積在Controller端
MVC的控制器,內(nèi)里封裝了通訊,容易變成大而全的高度耦合的集中器。比如將業(yè)務(wù)邏輯寫(xiě)在控制器里。
2.正確的開(kāi)發(fā)觀念
1)關(guān)注點(diǎn)分離
關(guān)注點(diǎn)分離的意思就是,當(dāng)你在進(jìn)行軟件開(kāi)發(fā)時(shí),可以只關(guān)注于當(dāng)前的對(duì)象上,一次僅關(guān)注于一個(gè)較容易理解與解決的部分,不要受到相同系統(tǒng)中其他對(duì)象的干擾,也包括對(duì)對(duì)象所做出的修正不會(huì)影響到其他對(duì)象的動(dòng)作,能夠?qū)W⒂谕瓿墒诌叺墓ぷ鳎坏菀滋嵘浖|(zhì)量,也可加快程序代碼理解的速度。
2)以習(xí)慣替換配置
以習(xí)慣替換配置是一種軟件設(shè)計(jì)模式,主要目的在于減少開(kāi)發(fā)人員在架構(gòu)時(shí)所決策的時(shí)間以及降低軟件設(shè)計(jì)過(guò)于彈性,而導(dǎo)致太復(fù)雜的情況,通過(guò)約定俗成的“開(kāi)發(fā)習(xí)慣”,讓同一群人員得以共享同一套設(shè)計(jì)架構(gòu),減少思考時(shí)間,降低溝通成本,且不失軟件開(kāi)發(fā)的彈性。
四、ASP.NET MVC應(yīng)用中的請(qǐng)求處理
ASP.NET MVC開(kāi)發(fā)模式不同于WebForm方式,不能直接訪(fǎng)問(wèn)視圖,必須通過(guò)控制器,那么很多人可能會(huì)不理解其資源的請(qǐng)求處理方式,以下簡(jiǎn)要介紹其請(qǐng)求處理過(guò)程。
1.每個(gè)HTTP請(qǐng)求的目標(biāo)是Controller中的一個(gè)Action,具體體現(xiàn)為定義在Controller類(lèi)型中的一個(gè)public方法。所以對(duì)請(qǐng)求的處理最終體現(xiàn)為對(duì)目標(biāo)Controller對(duì)象的激活和對(duì)目標(biāo)Action方法的執(zhí)行。
2.Controller的類(lèi)型和Action方法的名稱(chēng)及作為Action方法的部分參數(shù)可以直接通過(guò)請(qǐng)求的Url解析出來(lái)。
3.通過(guò)一個(gè)攔截器對(duì)抵達(dá)Web服務(wù)器的HTTP請(qǐng)求進(jìn)行攔截。這個(gè)攔截器根據(jù)當(dāng)前請(qǐng)求解析出目標(biāo)Controller的類(lèi)型和對(duì)應(yīng)的Action方法的名稱(chēng),隨后目標(biāo)Controller被激活,相應(yīng)的Action方法被執(zhí)行。
4.Action方法執(zhí)行過(guò)程中,可以調(diào)用Model獲取相應(yīng)的數(shù)據(jù)及改變其狀態(tài)。在Action執(zhí)行的最后階段一般會(huì)創(chuàng)建出一個(gè)View,后者最終被轉(zhuǎn)換為HTML以HTTP響應(yīng)的形式返回到客戶(hù)端。
5.綁定在View上的數(shù)據(jù)被稱(chēng)為ViewModel,來(lái)源于Model或者基于顯示要求進(jìn)行的簡(jiǎn)單邏輯計(jì)算。
五、總結(jié)
在軟件的開(kāi)發(fā)中,最常發(fā)生的問(wèn)題就是需求的變化。經(jīng)常改變的需求,對(duì)于軟件質(zhì)量與可維護(hù)性有很大的殺傷力,但這是事實(shí),我們無(wú)法改變。而MVC設(shè)計(jì)模式以一種概念簡(jiǎn)單卻又權(quán)責(zé)分明的架構(gòu),通過(guò)商業(yè)邏輯與數(shù)據(jù)表現(xiàn)的分離,可以撰寫(xiě)出更模塊化、可維護(hù)性高的程序代碼。本文介紹了MVC模式的基本概念;ASP.NET MVC的三個(gè)基本部件及其間關(guān)系;并對(duì)ASP.NET MVC開(kāi)發(fā)的正確觀念與其HTTP請(qǐng)求的處理過(guò)程進(jìn)行了簡(jiǎn)要的介紹,便讀者對(duì)ASP.NET MVC應(yīng)用程序的開(kāi)發(fā)有一個(gè)全面而正確的理解與認(rèn)識(shí)。
參考文獻(xiàn):
[1]黃保翕.ASP.NET MVC4開(kāi)發(fā)指南[M].清華大學(xué)出版社,2013年
[2]鄒瓊俊.ASP.NET MVC企業(yè)級(jí)實(shí)戰(zhàn)[M]:清華大學(xué)出版社,2017年
[3]弗瑞曼[美].精通ASP.NET MVC5[M]:人民郵電出版社,2016年