Scott Gu教你使用ASP.NET MVC 2新功能
ASP.NET開發(fā)團隊剛發(fā)布了ASP.NET MVC第二版的***個公開的預(yù)覽版。你可以在這里下載。
今天的預(yù)覽版是在.NET 3.5 SP1和VS 2008下工作的,可與ASP.NET MVC 1.0并行安裝在同一個機器上(即,它們不相沖突,如果你安裝2.0的話,你現(xiàn)有的ASP.NET MVC 1.0項目不會受影響)。如果你同時安裝ASP.NET MVC 1.0 和 ASP.NET MVC 2.0的話,你會在Visual Studio 2008的 “新項目” 對話框中看到2個ASP.NET MVC項目模板:
ASP.NET MVC 2預(yù)覽版的發(fā)布說明詳述了如何將現(xiàn)有的ASP.NET MVC 1.0項目升級到使用V2,如果你想將它們移植來利用V2的新特性的話。
新特性
ASP.NET MVC V2將包括一堆新功能和特性(其中一些已經(jīng)在ASP.NET MVC產(chǎn)品路線圖網(wǎng)頁上列出了)。今天的“***個預(yù)覽版”包括的一些新特性還是***次露面,更多的特性將在將來的預(yù)覽版中出現(xiàn)。***個預(yù)覽版的代碼還屬于早期版本,開發(fā)團隊今天發(fā)布這個版本,意在開始征詢大家的反饋,并將它們?nèi)谌雽淼陌姹尽?/P>
下面簡短地說明一下其中一些新功能:
區(qū)域支持
ASP.NET MVC 2將支持一個叫“區(qū)域(areas)”的新特性,允許你輕松地將MVC應(yīng)用的功能進行分割和組合。
“區(qū)域”提供了一個將控制器和視圖進行分組的方式,允許你把一個大應(yīng)用的各個子部分相對獨立地進行構(gòu)建。每個區(qū)域可以一個單獨的ASP.NET MVC項目的形式來實現(xiàn),并且這些項目可進而為主應(yīng)用所引用。這在建造大應(yīng)用時有助于管理其復(fù)雜性,并方便多個團隊合作開發(fā)應(yīng)用。
下面這個屏幕截圖展示一個單一解決方案中有三個項目。其中一個項目叫“CompanySite”(公司網(wǎng)站),包括了核心的網(wǎng)站內(nèi)容,布局,相關(guān)的控制器和視圖。還有2個單獨的“區(qū)域”項目: “Blogs”(博客) 和 “Forums” (論壇)。這2個項目實現(xiàn)了網(wǎng)站的/Blogs 和 /Forums URL下的功能,封裝了所有的路徑規(guī)則,以及實現(xiàn)這2個部分的控制器和視圖:
***個預(yù)覽版只包括了區(qū)域特性實現(xiàn)的***個部分,還不包括任何工具支持(目前,你只能手工添加編譯任務(wù)來創(chuàng)建并配置區(qū)域項目)。將來的預(yù)覽版本將包括工具支持,同時進一步將功能集擴大和完善。
#p#
DataAnnotation(數(shù)據(jù)標記)驗證支持
ASP.NET MVC 2現(xiàn)在包含了對***在.NET 3.5 SP1中發(fā)布的DataAnnotation驗證的內(nèi)置支持,這個東西是在ASP.NET動態(tài)數(shù)據(jù)和.NET RIA服務(wù)中使用的。DataAnnotation提供了一個簡易的方式,可以聲明的方式在應(yīng)用中的Model(模型)和ViewModel(視圖模型)類中添加驗證規(guī)則,在ASP.NET MVC中有自動的綁定和UI輔助方法驗證支持。
要看該特性如何在實際中使用,我們可以象下面這樣創(chuàng)建一個新的“Customer” 視圖模型類,內(nèi)含5個屬性(是用了C#特性之一 -- 自動屬性來實現(xiàn)的)。
然后,我們可以使用System.ComponentModel.DataAnnotations命名空間下的DataAnnotation特性,在這些屬性上飾于適當?shù)尿炞C規(guī)則。下面的代碼使用了4種不同的內(nèi)置驗證規(guī)則: Required], [StringLength], [Range], 和 [RegularExpression]。該命名空間下還包括一個基類,ValidationAttribute, 你可以繼承來創(chuàng)建你自己的定制驗證特性。
然后,我們可以創(chuàng)建一個CustomersController類,其中有2個 Create action方法。***個 Create action方法處理對應(yīng)于“/Customers/Create” URL的HTTP GET請求,基于一個空白的Customer對象顯示一個視圖模板。第二個 Create action方法則處理同個URL的HTTP POST請求,并接受一個Customer對象作為方法參數(shù)。它會檢查提交的輸入數(shù)據(jù)是否造成了任何模型綁定錯誤,如果造成了錯誤的話,它會使用已經(jīng)輸入的數(shù)據(jù)重新顯示視圖模板,如果沒錯誤的話,它會給用戶顯示一個提交成功了的視圖:
***,我們可以在上面任意一個Create action方法中右擊,選擇 “添加視圖”上下文菜單命令,自動地生成(scaffold)一個基于Customer對象的“Create”視圖模板的框架。這么做的話,生成的框架視圖模板會包含下面這樣一個HTML < form>:
這樣,當我們在瀏覽器中請求“/Customers/Create” URL時,我們會得到象下面這樣起始的空白表單:
如果我們輸入不合法的數(shù)據(jù),提交到服務(wù)器時,ASP.NET MVC 2模型綁定器會檢測到我們的Customer類上有DataAnnotations特性,會自動地使用它們對提交的表單輸入數(shù)據(jù)進行驗證。如果有錯誤的話,我們的控制器action方法會重新顯示表單,并且給用戶顯示適當?shù)尿炞C錯誤消息,象下面這樣。注意我們使用DataAnnotation特性指定的驗證屬性錯誤消息字符串是如何通過Html.Validation輔助方法顯示給用戶的,不用編寫額外的代碼就可以實現(xiàn)。
在將來的ASP.NET MVC 2預(yù)覽版中,我們計劃將jQuery驗證插件作為默認項目模板的一部分來發(fā)布,同時添加DataAnnotation驗證規(guī)則在客戶端JavaScript中自動強制執(zhí)行的支持。這將允許開發(fā)人員輕松地在一個地方,Model或ViewModel對象上,添加驗證規(guī)則,然后無論對象用在應(yīng)用中的什么地方,這些規(guī)則都會同時在客戶端和服務(wù)器端強制執(zhí)行。
如果你不希望直接標記你的模型或視圖模型類,你還可以創(chuàng)建一個伴隨你的模型類的“伙伴類(buddy class)”,另外封裝DataAnnotaton規(guī)則。這個功能還在這樣一些場景下有用: VS直接生成/更新類的屬性代碼,你無法簡易地在生成的代碼上飾以特性(例如,由LINQ to SQL 或 LINQ to Entities設(shè)計器生成的類)。
除了提供對DataAnnotations的內(nèi)置支持外,ASP.NET MVC V2中的DefaultModelBinder類現(xiàn)在還有新的虛擬方法,可以在子類中覆蓋,來輕松地集成其他的驗證框架( 例如Castle Validator, EntLib Validation等等)。ASP.NET MVC中的驗證UI輔助方法是設(shè)計來支持任何類型的驗證框架的(它們不用知道DataAnnotations)。
#p#
強類型UI輔助方法
ASP.NET MVC V2包含了新的HTML UI輔助方法,這些輔助方法允許你在引用視圖模板的模型對象時使用強類型的lambda表達式。這可以促成更好的視圖編譯時檢查(這樣缺陷是在編譯時發(fā)現(xiàn)而不是在運行時發(fā)現(xiàn)),還能促成視圖模板中更好的代碼intellisense支持。
你可以在下面看到一個示范更好intellisense的例子,注意我在使用新的Html.EditorFor()輔助方法時是如何得到Customer模型對象屬性的完整列表的:
***個預(yù)覽版提供對新的Html.EditorFor(), Html.LabelFor(), 和 Html.DisplayFor() 輔助方法的內(nèi)置支持。將在這個星期發(fā)布的更新過的MVC Futures程序集還將包含對另外的Html.TextBoxFor(), Html.TextAreaFor(), Html.DropDownListFor(), Html.HiddenFor(), 和 Html.ValidationMessageFor()輔助方法的支持(隨著時間的推移,這些方法也會移到核心ASP.NET MVC 2程序集中去)。
在下面,你可以看到Customer創(chuàng)建場景下“Create”視圖模板的一個更新了的版本。注意,在UI輔助方法中,我們不是使用字符串表達式來引用Customer對象,而是使用強類型的lambda表達式。我們在所有這些方法中都可以得到完整的 intellisense 和 編譯時檢查:
上面的Html.LabelFor()輔助方法生成< label for="Name">Name:< /label> HTML 標識。
Html.EditorFor()輔助方法可以用于任何數(shù)據(jù)類型值。在默認情形下,它很聰明,會根據(jù)要編輯的類型輸出合適的HTML < input/>元素。譬如,它會為上面的前4個屬性(是字符串和整數(shù)類型)生成< input type=”text”/>元素,會為***的那個“IsActive” 屬性生成< input type=”checkbox”/>元素,因為這個屬性是布爾值類型。
除了支持簡單的數(shù)據(jù)類型外,Html.EditorFor()輔助方法還允許你傳遞給它擁有多個屬性的比較復(fù)雜的對象。在默認情形下,它會對對象的所有公開屬性進行循環(huán),輸出< label>, < input/> 元素,以及它能找到的每個屬性的任何合適的驗證消息。例如,我們可以重寫上面的視圖,對Customer對象只做單個Html.EditorFor()調(diào)用,從概念上來說輸出跟上面一樣的標識:
強類型的輔助方法允許你在Customer視圖類的屬性上飾以[DisplayName]特性,來控制為每個屬性輸出的標簽字符串(例如:不是用“IsActive”作為標簽文字,我們可以加一個[DisplayName(“Is Active Customer:”)]特性)。
你也可以加一個[ScaffoldColumn(false)]特性,來表示,在象上面把一個復(fù)雜的對象傳給Html.EditorFor()那樣的場景下,某個特定的屬性完全不應(yīng)該顯示出來。
#p#
UI 輔助方法模板化支持
Html.EditorFor() 和 Html.DisplayFor() 輔助方法對顯示標準的數(shù)據(jù)類型以及含有多個屬性的復(fù)雜對象有內(nèi)置的支持。就象上面說的,它們還支持通過在視圖模型上施加象[DisplayName]和 [ScaffoldColumn]特性這樣的基本的定制機制。
但經(jīng)常地,開發(fā)人員想要能夠進一步定制UI輔助方法的輸出,對生成的東西要有完全的控制。Html.EditorFor() 和 Html.DisplayFor()輔助方法通過一個模板化機制支持這個要求,這個機制允許你定義外部的模板,替換原先的,完全控制顯示的輸出。更棒的是,你還可以在每個數(shù)據(jù)類型/類的基礎(chǔ)上定制要顯示的內(nèi)容。
在***個預(yù)覽版中,你可以在\Views\[控制器名稱]目錄下(如果你想要定制某個特定的控制器所用視圖的顯示的話)或在\Views\Shared目錄下(如果你想要定制一個應(yīng)用中所有視圖和控制器的顯示的話)加一個“EditorTemplates” 或者 “DisplayTemplates” 子目錄。
然后你可以往這些目錄中加分模板(partial template)文件,針對個別數(shù)據(jù)類型或者類來定制顯示輸出。例如,在下面,我在\Views\Shared目錄下加了一個EditorTemplates子目錄,在其中加了三個定制的模板文件:
上面的“Customer.ascx”模板表示我想要定制在調(diào)用Html.EditorFor()時其參數(shù)為Customer對象時的輸出(例如,我可以定制Customer屬性的精確順序和布局)。上面的“DateTime.ascx” 模板表示我想要定制在調(diào)用Html.EditorFor()時其參數(shù)為DateTime屬性時的輸出(例如,我也許想要使用JavaScript的日歷控件,而不是普通的文本框)。我也可以在目錄中加一個“Object.ascx” 模板,如果我想要替代所有對象的默認顯示的。
除了在每個類的基礎(chǔ)上定制輸出外,你還可以在目錄中加“具名模板(named templates)”。一個常見的場景也許是 “CountryDropDown”模板,它處理字符串數(shù)據(jù)類型,但不是提供標準的文本框,而是顯示一個用戶可以選擇的列出了國家名稱值的< select>下拉框。下面是這個編輯器模板的一個例子:
然后,我們可以在調(diào)用Html.EditorFor()輔助方法時,把上面這個模板的名稱作為參數(shù)傳給它,明確地表示我們想要使用這個模板。例如,在下面,除了指定Country屬性的lambda表達式外,我們還指定了在顯示時要使用的編輯器模板的名稱:
或者,你也可以在你的ViewModel屬性和類型上指定“UIHint”特性。這允許你在單一一個地方指定要使用的默認編輯器或者顯示器模板,然后在整個應(yīng)用的所有視圖中使用指定的模板(而不必顯式地將這個名稱作為參數(shù)傳給Html.EditorFor)。
下面是一個如何使用UIHint特性來表示Customer.Country屬性(字符串類型)應(yīng)該在默認情形下顯示時使用CountryDropDown模板的例子:
一旦在我們的視圖模型上設(shè)置上述特性后,在使用Html.EditorFor()顯示那個屬性時,我們就不再需要顯式指定模板名稱了。現(xiàn)在,在/Customers/Create URL上點擊刷新時,我們的Country屬性就會顯示為一個下拉框,而不是一個標準的文本框:
#p#
其他酷特性
ASP.NET MVC 2***個預(yù)覽版還包含了若干個雖小但是很妙的特性。我最喜愛的幾個包括:
新的[HttpPost]特性
在 ASP.NET MVC中,把一個URL的處理分成2個action方法的做法是非常常見的,其中一個處理GET請求,另一個處理POST請求。
在ASP.NET MVC 1中,你使用[AcceptVerbs(HttpVerbs.Post)]特性來表示action方法的“Post”版本:
在ASP.NET MVC 2中這依然工作,但你現(xiàn)在也可以利用更簡潔的[HttpPost]特性來做同樣的事情:
默認參數(shù)值
處理可省參數(shù)在web場景中是司空見慣的事。在ASP.NET MVC 1中,處理可省參數(shù)一般有2個做法,通過注冊定制的路徑規(guī)則,在其中指定默認的值,或者將某個action方法的參數(shù)標記為nullable,然后在action方法中添加代碼處理該參數(shù)是否是null(如果是null就提供默認值)。
ASP.NET MVC 2***個預(yù)覽版現(xiàn)在支持在action方法的參數(shù)上飾以System.ComponentModel命名空間下的DefaultValueAttribute。這允許你在某個參數(shù)不在請求值中時指定ASP.NET MVC應(yīng)該傳給action方法的參數(shù)值。例如,下面是一個我們可以如何處理 /Products/Browse/Beverages 和 /Products/Browse/Beverages?page=2 URLs的例子,如果“page”參數(shù)不是查詢字符串的一部分時,其值為“1”:
VB今天就允許你直接在語言中指定默認的參數(shù)值(而不必象上面那樣顯式指定DefaultValue特性),VS2010中的C#語言也將支持可省參數(shù)的默認值,將允許我們把上面的代碼簡化成:
這應(yīng)該會使處理默認/可省場景變得非常地干凈利落。
綁定二進制數(shù)據(jù)
ASP.NET MVC 2的***個預(yù)覽版還加了支持綁定base64編碼的字符串值到類型為byte[]和System.Data.Linq.Binary的屬性?,F(xiàn)在還有2個可以接受這些數(shù)據(jù)類型的重載的Html.Hidden()版本。在你想要在應(yīng)用中啟用并發(fā)性控制,在表單中來回傳送數(shù)據(jù)庫行記錄的時間戳(timestamp)值的場景下,這會非常有用。
結(jié)語
點擊這里下載包含一個ASP.NET MVC 2項目的.zip文件,該項目實現(xiàn)了我在上面示范的樣例。
今天的ASP.NET MVC 2版本還只是***個預(yù)覽版,將來的預(yù)覽版中將包括更多的特性,開發(fā)團隊期待在如何改進和增強功能方面得到許許多多的反饋。
有規(guī)律地發(fā)布這些預(yù)覽版的目的是想幫助確保這個反饋過程是開放的,任何想?yún)⑴c的人都可以輕易地參與。請在www.asp.net的ASP.NET MVC論壇上發(fā)貼提反饋,建議或者貼出你遇到的問題等。 你也可以從Phil Haack的MVC2貼子 和 Phil和 Scott Hanselman在Channel9錄制的關(guān)于***個預(yù)覽版的錄像中了解這個預(yù)覽版的詳情。
希望本文對你有所幫助,
Scott
【編輯推薦】