【转】Scott_ASP.NET MVC框架(第三部分) 把ViewData从控制器传到视图
Scott的MVC框架系列,非常好的MVC學(xué)習(xí)資料。很適合初學(xué)者閱讀。做為一個系列轉(zhuǎn)載過來,純粹是為了學(xué)習(xí)方便。
文章轉(zhuǎn)自:Scott Guthrie 博客中文版
【原文地址】ASP.NET MVC Framework (Part 3): Passing ViewData from Controllers to Views
【原文發(fā)表日期】 Thursday, December 06, 2007 2:49 AM
【譯注】根據(jù)Scott Guthrie原文的回復(fù),ASP.NET MVC框架的第一個CTP將于12月7日發(fā)布
過去的幾個星期內(nèi),我一直在寫著討論我們正在開發(fā)的新ASP.NET MVC框架的系列貼子。ASP.NET MVC框架是個你可以用來結(jié)構(gòu)化你的ASP.NET web應(yīng)用,使之擁有清晰的關(guān)注分離,方便你單元測試代碼和支持TDD流程的可選方法。
這個系列的第一篇建造了一個簡單的電子商務(wù)產(chǎn)品列表/瀏覽網(wǎng)站。它討論了MVC后面的高層次的概念,示范了如何從頭創(chuàng)建一個新的ASP.NET MVC項目,實現(xiàn)和測試這個電子商務(wù)產(chǎn)品列表功能。系列的第二篇對ASP.NET MVC框架的URL路徑選擇(routing)架構(gòu)做了深入探討,討論了它的工作原理以及你如何使用它來處理更高級的URL路徑選擇場景。
在今天的帖子里,我將討論控制器是如何與視圖做交互的,具體來說,我將討論你可以把數(shù)據(jù)從控制器傳到視圖以顯示返回到客戶端的回復(fù)的各種方式。
第一部分的扼要簡述
在這個系列的第一部分,我們創(chuàng)建了一個電子商務(wù)網(wǎng)站,實現(xiàn)了基本的產(chǎn)品列表/瀏覽支持。我們是用ASP.NET MVC框架實現(xiàn)這個網(wǎng)站的,這個方法會很自然地將代碼結(jié)構(gòu)化為獨特的控制器,模型和視圖組件。
當(dāng)瀏覽器向我們的網(wǎng)站發(fā)送一個HTTP請求時,ASP.NET MVC框架將使用它的URL路徑選擇引擎,把進來的請求映射到一個控制器上的action方法來處理它。在基于MVC的應(yīng)用中的控制器負(fù)責(zé)處理進來的請求,處理用戶輸入和交互,執(zhí)行基于這些輸入和交互的應(yīng)用邏輯(獲取或更新存儲在數(shù)據(jù)庫中的模型數(shù)據(jù)等等)。
到生成返回到客戶端的HTML回復(fù)的時候,控制器一般是與“視圖”組件合作,這些視圖組件是以獨立于控制器的單獨的類或模板的形式實現(xiàn)的,其目的是完全注重于封裝顯示邏輯。
視圖不應(yīng)該含有任何應(yīng)用邏輯或數(shù)據(jù)庫訪問代碼,所有的應(yīng)用/數(shù)據(jù)邏輯應(yīng)該由控制器類來處理。這么劃分的動機是幫助強制你的應(yīng)用/數(shù)據(jù)邏輯與界面生成代碼間的清晰分離。同時這也方便你獨立于你的界面顯示邏輯來單元測試你的應(yīng)用/數(shù)據(jù)邏輯。
視圖應(yīng)該只使用從控制器傳過來的特定于視圖的數(shù)據(jù)來生成輸出。在ASP.NET MVC框架中,我們稱這個特定于視圖的數(shù)據(jù)為“ViewData”。這個博客的其他部分將討論你可以用來將ViewData從控制器傳遞給視圖來生成顯示的一些不同方法。
一個簡單的產(chǎn)品列表場景
為幫助說明我們可以用來把ViewData從控制器傳遞給視圖的一些技術(shù),讓我們來建造一個簡單的產(chǎn)品列表網(wǎng)頁:
我們將用一個CategoryID整數(shù)來過濾我們想要顯示在頁面上的產(chǎn)品。注意上面我們是如何把CategoryID嵌在URL中的(例如,Products/Category/2 或 /Products/Category/4 )。
然后,我們的產(chǎn)品列表網(wǎng)頁顯示了2個不同的動態(tài)內(nèi)容元素。第一個元素是我們要顯示的分類的文本名稱(例如,Condiments-調(diào)味品),第二個元素是一個HTML <ul><li/></ul> 產(chǎn)品名字列表。我在上面的屏幕截圖中對這2個元素用紅筆畫了圈。
在下面,我們將看一下我們可以使用的2個不同的方法來實現(xiàn)ProductsController類,這個類處理進來的請求,獲取處理請求所需的數(shù)據(jù),然后將這個數(shù)據(jù)傳給一個List視圖來顯示。我們要研究的第一個方法是用后期綁定的字典對象傳遞這個數(shù)據(jù),第二個方法則使用強類型類的方式來傳遞這個數(shù)據(jù)。
方法 1:使用 Controller.ViewData 字典來傳遞ViewData
Controller基類有個ViewData字典屬性,可以用來填充你要傳給視圖的數(shù)據(jù)。你使用鍵/值模式將對象加入 ViewData 字典。
下面是個ProductsController類,其中的Category action方法實現(xiàn)了我們上面的產(chǎn)品列表場景。注意,它是如何使用分類的ID參數(shù)來查詢該分類的文本名稱,以及獲取該分類中的產(chǎn)品列表的。它使用“CategoryName”和“Products”兩個鍵將這兩個數(shù)據(jù)存儲在Controller.ViewData 集合中:
?
然后,我們上面的Category action方法調(diào)用 RenderView("List") 來表示它要用哪個模板來做顯示。當(dāng)你象這樣調(diào)用RenderView時,它會將ViewData字典傳給視圖,以顯示對應(yīng)的回復(fù)。
實現(xiàn)我們的視圖
我們將使用居于我們項目的\Views\Products目錄下的List.aspx文件來實現(xiàn)我們的List視圖。這個 List.aspx 將繼承 \Views\Shared 文件夾中的Site.Master母版頁中的布局(在你創(chuàng)建一個新的視圖網(wǎng)頁時,你可以在 VS 2008 中,右擊,選擇添加新項->MVC視圖內(nèi)容網(wǎng)頁來接連一個母版頁):
當(dāng)我們使用MVC視圖內(nèi)容網(wǎng)頁模板來創(chuàng)建List.aspx網(wǎng)頁時,它不是從通常的 System.Web.UI.Page 類繼承而來,而是從System.Web.Mvc.ViewPage 基類繼承而來(是現(xiàn)有的Page類的一個子類):
ViewPage基類提供一個ViewData字典屬性,我們可以在視圖網(wǎng)頁里訪問由控制器添加的數(shù)據(jù)對象。然后我們可以取出這些數(shù)據(jù)對象,使用它們來顯示HTML輸出,可以用服務(wù)器控件的方式,或者用 <%= %> 顯示代碼的方式。
使用服務(wù)器控件來實現(xiàn)我們的視圖
下面是一個如何使用現(xiàn)有的<asp:literal> 和 <asp:repeater>服務(wù)器控件來實現(xiàn)我們的HTML界面的例子:
我們可以用下面的后臺代碼類將 ViewData 綁定到這些控件之上(注意我們是如何使用ViewPage的ViewData字典來實現(xiàn)的 ):
注: 因為頁面上沒有 <form runat="server">,是不會輸出 view-state 的。上面的控件也不會自動生成任何ID值,這意味著你對輸出的HTML有完全的控制。
使用 <%= %> 代碼來實現(xiàn)我們的視圖
如果你更喜歡使用行內(nèi)代碼來生成輸出的話,你可使用下面的 List.aspx 來實現(xiàn)跟上面完全一樣的結(jié)果:
注: 因為ViewData的類型是含有“objects”的字典,為了對它使用foreach語句,我們需要將ViewData["Products"]的類型轉(zhuǎn)換成 List<Product> 或者 IEnumerable<Product>。我在頁面上引用了System.Collections.Generic 和 MyStore.Models 命名空間 以避免輸入 List<T> 和 Product 類型的完整名稱。
注: 上面使用了“var”關(guān)鍵詞,這是VS 2008中新的 C# 和 VB “類型推斷”特性的一個例子(在這里閱讀我以前的相關(guān)貼子)。因為我們將ViewData["Products"] 轉(zhuǎn)換成了 List<Product>,我們在 List.aspx 文件中的 prduct 變量上得到了完整的intellisense:
方法 2:使用強類型類來傳遞ViewData
除了支持后期綁定的字典方法外,ASP.NET MVC框架還允許你把強類型的ViewData對象從控制器傳遞給你的視圖。使用這個強類型的方法有幾個好處:
下面是一個強類型的ProductsListViewData類,封裝了 List.aspx 視圖顯示我們的產(chǎn)品列表所需的數(shù)據(jù),它含有 CategoryName 和 Products 屬性(是通過使用新的C#自動屬性支持來實現(xiàn)的):
然后我們可以更新我們的 ProductsController 實現(xiàn)來使用這個對象,把一個強類型的ViewData對象傳給我們的視圖:
注意上面,我們是如何通過 RenderView() 方法的一個額外的參數(shù),把我們的強類型 ProductsListViewData 對象傳給View的。
把視圖的ViewData字典與強類型的ViewData對象一起使用
前面我們編寫的 List.aspx 視圖實現(xiàn)會繼續(xù)和我們更新過的 ProductsController 協(xié)作,不需改動代碼。這是因為,當(dāng)把一個強類型的 ViewData 對象傳遞給繼承自 ViewPage 的視圖類時,ViewData 字典會自動使用反射對強類型的對象的屬性做查詢?nèi)≈怠K晕覀兿笙旅孢@樣的視圖中的代碼:
會自動使用反射來從強類型的 ProductsListViewData 對象中獲取 CategoryName 屬性,這個對象是我們在調(diào)用 RenderView 方法時傳入的。
使用ViewPage<T>基類來對ViewData強類型化
除了支持基于字典的ViewPage基類外,ASP.NET MVC框架中還發(fā)布有基于泛型的 ViewPage<T> 實現(xiàn)。如果你的視圖是從 ViewPage<T> 繼承而來,這里T表示是控制器傳給視圖的 ViewData 的類型,那么 ViewData 屬性就將是使用了這個T類的強類型屬性。
例如,我們可以更新我們的 List.aspx.cs 后臺代碼類,不是從ViewPage繼承來,而是繼承自 ViewPage<ProductsListViewData> :
這么做之后,頁面上的 ViewData 屬性將會從一個字典變成屬于 ProductsListViewData 類型。這意味著,我們現(xiàn)在可以不再使用基于字符串的字典來查閱獲取數(shù)據(jù),而是可以使用強類型的屬性了:
然后,我們可以使用服務(wù)器控件的方法,或者 <%= %> 顯示的方法來生成基于這個ViewData的HTML。
使用服務(wù)器控件來實現(xiàn) ViewPage<T>視圖
下面是一個例子,我們可以使用<asp:literal> 和 <asp:repeater>服務(wù)器控件來實現(xiàn)我們的HTML界面。這是我們使用繼承自 ViewPage 的 List.aspx 網(wǎng)頁時所使用的完全一樣的標(biāo)識:
下面是相應(yīng)的后臺代碼。注意,因為我們是從 ViewPage<ProductsListViewData> 繼承而來的,我們可以直接訪問它的屬性,而不要對任何東西做類型轉(zhuǎn)換(什么時候我們決定對其中一個屬性改名的話,我們還將得到重構(gòu)工具的支持):
使用 <%= %> 代碼實現(xiàn)我們的 ViewPage<T> 視圖
如果你更喜歡使用行內(nèi)代碼來生成輸出的話,你可以象下面這樣在 List.aspx 中達(dá)成跟上面一樣的結(jié)果:
使用 ViewPage<T> 方法,我們現(xiàn)在不再需要對 ViewData 使用字符串查閱了。更重要的是,注意上面,我們不再需要對任何屬性做類型轉(zhuǎn)換了,因為它們已經(jīng)是強類型的。這意味著,我們可以編寫 foreach (var product in ViewData.Products) ,而不用對 Products 做類型轉(zhuǎn)換。我們還在循環(huán)中的 product 變量上得到了完整的intellisense:
結(jié)語
希望本貼子提供了關(guān)于控制器如何把數(shù)據(jù)傳遞給視圖以顯示返回到客戶端的回復(fù)的一些細(xì)節(jié)。你可以使用后期綁定的字典,或者使用強類型的方式來達(dá)成這個目的。
第一次試著建造MVC應(yīng)用時,你很可能發(fā)現(xiàn)把應(yīng)用控制器的邏輯和生成界面的代碼分離開來的概念有點怪。你大概要花上一段專門的時間來多建造些應(yīng)用,你才會感到習(xí)慣,把自己的思路轉(zhuǎn)向到處理一個請求,執(zhí)行所有的應(yīng)用邏輯,把建造界面回復(fù)所需的 viewdata 包裝起來,然后交給單獨的一個視圖頁面去顯示的觀念上去。 重要事項:如果這個模型對你來說并不感覺舒服,那么別用它,MVC的方法純粹是可選的,我們并不認(rèn)為這是每個人都想要用的東西。
但這個劃分應(yīng)用的好處以及其后的目標(biāo)在于,它允許你獨立于你的界面顯示代碼,來運行和測試你的應(yīng)用和數(shù)據(jù)邏輯。這極大地方便你為你的應(yīng)用開發(fā)全面的單元測試,以及在建造應(yīng)用時使用TDD(測試驅(qū)動開發(fā))的流程。在以后的貼子里,我會對此做更深入的討論,以及討論你可以用來輕松測試代碼的最佳實踐。
希望本文對你有所幫助,
Scott
轉(zhuǎn)載于:https://www.cnblogs.com/tenghoo/archive/2009/03/11/1408457.html
總結(jié)
以上是生活随笔為你收集整理的【转】Scott_ASP.NET MVC框架(第三部分) 把ViewData从控制器传到视图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FMS3系列(二):创建可交互的FMS连
- 下一篇: asp.net ajax控件工具集 Au