ASP.NET MVC3書店--第三節+視圖與視圖模型

     現在我們已經可以從控制器的action方法中返回字符串了。我們可以藉此來理解控制器是如何來工作的。但在真正的Web應用程序中大多數情況下返回的都不僅僅是一個字符串。我們更需要的是當用戶輸入URL地址請求時,能夠返回給瀏覽器一串HTML格式的輸出流,我們可以藉由模板文件來更方便地定製這個HTML格式的輸出流,並將其返回。在ASP.NET MVC中,將這個模板文件稱之爲視圖。

3.1    追加一個視圖模板

    爲了要使用視圖模板,我們修改HomeController控制器中的Index方法,使其返回一個ActionResult對象,並且將return語句修改爲return View(),代碼如下所示。

public class HomeController : Controller

{

    //

    // GET: /Home/

    public ActionResult Index()

    {

        return View();

    }

}

    接下來,我們在應用程序中追加一個視圖模板。在Index這個action方法中點擊鼠標右鍵,然後點擊“添加視圖”,如圖3-1所示。 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-1 添加視圖

    點擊“添加視圖”後,彈出一個“添加視圖”對話框,如圖3-2所示。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-2 添加視圖對話框

    添加視圖對話框使我們可以快速地、方便地產生視圖模板文件。在默認情況下,添加視圖對話框將使用該視圖的action方法的名字作爲視圖模板的名字。這裏,因爲我們在HomeController控制器中的Index方法中點擊了“添加視圖”子菜單,所以在添加視圖對話框中的視圖模板名字默認爲“Index”。在該對話框中,不做任何修改,直接點擊添加按鈕。

    點擊添加按鈕之後,Visual Web Developer將會在Views文件夾下的Home文件夾中自動爲我們創建一個名爲Index.cshtml的視圖模板文件,如圖3-3所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-3 Index.cshtml視圖模板文件已被創建

    Index.cshtml文件的命名與存放位置是非常重要的,而且也遵循了ASP.NET MVC的命名約定。“Views\Home”這個文件夾與HomeController控制器互相對應。Index這個視圖模板與控制器中返回該模板文件的Index方法互相對應。

當我們使用了這個默認的命名約定來返回一個視圖的時候,我們可以不用顯式地指定該視圖模板文件的存放位置。在HomeController控制器中書寫如下所示的代碼,瀏覽器將自動渲染“Views\Home”這個文件夾中的Index.cshtml視圖模板文件。

public class HomeController : Controller

{

    //

    // GET: /Home/

    public ActionResult Index()

    {

        return View();

    }

}
    查看Index.cshtml文件,代碼內容如下所示。
@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>
    在這段代碼中,使用到了Razor視圖引擎,該視圖引擎使用一種比在Web Forms與在之前版本的ASP.NET MVC中更加精簡的代碼書寫方法。在ASP.NET MVC3中,之前的WebForms仍然能夠繼續使用,但是很多開發者發現Razor視圖引擎更加適合ASP.NET MVC的開發。

    上面這三行代碼中使用ViewBag.Title屬性來設置在瀏覽器中進行顯示時的瀏覽器窗口標題。我們將很快能夠在瀏覽器中查看這一設置的結果,但這裏首先讓我們更新頁面中的標題文字,將<h2>標籤中的文字修改爲“網站首頁”,代碼如下所示。

@{

    ViewBag.Title = "首頁";

}

<h2>網站首頁</h2>
    運行應用程序,瀏覽器中的顯示結果如圖3-4所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-4 瀏覽器中的Index視圖

3.2 爲公共站點元素使用統一佈局

大多數網站中都有一個很多面共同使用的公共內容:航條,腳註,logo片,式表等等。Razor視圖引擎使用一個公共面來管理些公共內容,從而使得公共內容的使用與修改得更加容易。個公共面被命名“_Layout.cshtml”,在一始自動創用程序的候,個文件也被建於“/Views/Shared”文件中,如3-5所示。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-5 _Layout.cshtml文件已被創建

    雙擊打開該文件,文件中代碼如代碼清單3-1所示。

    代碼清單3-1 _Layout.cshtml文件中內容

<!DOCTYPE html>

<html>

<head>

    <title>@ViewBag.Title</title>

    <link href="@Url.Content("~/Content/Site.css")"

rel="stylesheet" type="text/css" />

    <script src="@Url.Content("~/Scripts/jquery- 1.4.4.min.js")"

type="text/javascript"></script>

</head>

<body>

    @RenderBody()

</body>

</html>
    MVC3書店這個Web網站擁有一個每個網頁上都會出現的公共標題與兩個公有鏈接,一個鏈接到我們的首頁,另一個鏈接到書籍種類列舉顯示頁面,所以我們將該文件中的代碼修改如代碼清單3-2所示。

    代碼清單3-2 添加了公共標題與公共鏈接的_Layout.cshtml文件

<!DOCTYPE html>

<html>

<head>

    <title>@ViewBag.Title</title>

    <link href="@Url.Content("~/Content/Site.css")"

rel="stylesheet" type="text/css" />

    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")"

type="text/javascript"></script>

</head>

<body>

    <div id="header">

        <h1>

            ASP.NET MVC 書店</h1>

        <ul id="navlist">

            <li class="first"><a href="/" id="current">首頁</a></li>

            <li><a href="/Store/">挑選書籍</a></li>

        </ul>

    </div>

    @RenderBody()

</body>

</html>
3.3 更新樣式表

一個空的項目模板中也會包括一個非常簡單的CSS樣式表文件,在該樣式表文件中只包括了顯示驗證信息時所用到的樣式。現在我們想在其中加入網站中所需要用到的其他的一些樣式與圖片,讓我們來看一下應該如何進行添加。首先我們可以將我們的樣式文件追加在Content文件夾下,將所有的圖片追加在Content文件夾下的Images文件夾下,如圖3-6所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-6 追加樣式表與圖片

    現在讓我們來運行我們的應用程序,看一下現在的首頁在瀏覽器中的顯示效果,如圖3-7所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-7 添加了樣式與圖片後的首頁

    現在讓我們暫時回顧一下Visual Web Developer能夠進行哪些工作:HomeController控制器的Index這個action方法能夠自動找到並顯示Views文件夾下的Home文件夾下的Index.cshtml這個視圖模板,而我們只需要在代碼中寫入“return View()”語句,因爲我們的視圖模板的命名與存放位置是遵循ASP.NET MVC3的標準約定的。

首頁中顯示了我們在視圖模板文件(Views文件夾下的Home文件夾下的Index.cshtml文件)中所指定的“網站首頁”文字。

首頁中使用了前面所講的_Layout.cshtml這個公共視圖模板文件,所以顯示出了在公共視圖模板文件中所指定的公共信息。

3.4    使用一個模型來將信息傳入我們的視圖 

    如果一個視圖模板文件中只是顯示靜態內容的話,是不可能使網站變得多麼生動有趣的。爲了要創建一個動態的Web網站,我們需要將信息從控制器傳入視圖模板文件中。

    在MVC(模型-視圖-控制器)框架中,“模型”用來映射應用程序中所使用到的各種數據。通常情況下,模型對象用來映射數據庫中的數據表,但也可以是其他數據。

    控制器中返回ActionResult對象的action方法可以將一個模型對象傳入視圖。這意味着控制器可以將生成一個響應流時所需要用到的所有數據進行封裝,然後傳入一個視圖模板文件,用以生成HTML格式的響應流。接下來我們用一個action方法爲例,來看看控制器如何將數據傳入視圖模板中。

    首先我們將要創建一些模型類,分別代表書店中的書籍種類信息與某本書籍的具體信息。爲了要創建一個Genre模型類(書籍種類),鼠標右擊Models文件夾,點擊“添加類”,如圖3-8所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-8 添加模型類

    在彈出的添加類對話框中,將類命名爲“Genre.cs”,如圖3-9所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-9 將模型類命名爲“Genre.cs”

    點擊添加按鈕,在打開的類文件中追加一個public(公有)的string(字符串)類型的Name(種類名稱)屬性,代碼如下所示。

public class Genre

{

    public int ID { get; set; }

    public string Name { get; set; }

}
    接下來,用同樣的方法添加一個Book(書籍)類,文件名爲Book.cs,添加一個Title(標題)屬性與一個Genre(書籍種類)屬性,代碼如下所示。

public class Book

{

    public string Title { get; set; }

    public Genre Genre { get; set; }

}

    接下來,讓我們修改StoreController控制器,使其能夠使用視圖,展示模型中的信息。

    首先,我們修改StoreController控制器中的Details這個action方法,使其能夠顯示單本書籍的信息。在StoreController控制器類的頭部追加一句using語句來引用MvcBookStore.Models命名空間。這樣我可以避免在每次使用Book類的時候都需要鍵入MvcBookStore.Models.Book。StoreController控制器類的頭部處using語句的代碼如下所示。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using MvcBookStore.Models;

    接下來,我們修改控制器中Details這個action方法,使其不再返回一個字符串,而是與HomeController控制器中的Index方法同樣,返回一個ActionResult對象,代碼如下所示。

public ActionResult Details(int id)

    現在我們修改Details方法內部的代碼,使其向視圖中傳入一個Book對象。在後文中我們將可以從數據庫中首先獲取一個Book(書籍)對象的數據,然後再將該Book對象傳入視圖,但是現在我們先暫時直接在代碼中直接寫入Book對象的數據,並傳入視圖,代碼如下所示。

public ActionResult Details(int id)

{

    var book = new Book { Title = "書籍 " + id };

    return View(book);

}

    注意:如果你對C#不很熟悉的話,你也許會認爲使用“var”聲明的話就意味着代碼中的book變量是後期綁定的。事實上並不是如此,C#編譯器使用類型引用的基礎是取決於我們給變量賦的值是什麼類型的,因爲book的類型是Book,所以編譯器把book變量編譯爲一個本地的Book類型的變量,所以我們仍然可以使用C#中的編譯時檢查和Visual Web Developer中的代碼智能輸入功能。

    現在讓我們創建一個顯示單本書籍信息的視圖模板。在這之前我們需要重編譯一下我們的應用程序,以確保在添加視圖對話框中的選擇模型類下拉框中可以找到我們剛加入的Book(書籍)模型類。你可以通過點擊“調試”菜單中的“生成 MvcBookStore”菜單項來進行編譯,如圖3-10所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-10 編譯應用程序

    現在我們的類已經編譯好了,我們可以追加這個展示單本書籍的視圖模板了。在Details方法中點擊鼠標右鍵,選擇“添加視圖”。如圖3-11所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

3-11Details方法中追加視圖

    我們要追加的視圖與之前在HomeController控制器中追加的視圖稍微有所不同,這一次我們在“添加視圖”對話框中勾選“創建強類型視圖”複選框,在模型類下拉框中選擇“Book(MvcBookStore.Models)”,如圖3-12所示。這樣的話添加出來的視圖模板會自動認爲已經從外面接收到了一個Book對象,並且自動追加視圖中對於該對象進行處理的代碼。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-12 添加展示單本書籍信息所用視圖

    點擊添加按鈕,在我們的Views文件夾下面的Store文件夾中會自動添加一個Details.cshtml模板文件,打開該文件,其中已經自動添加如下所示的代碼。

@model MvcBookStore.Models.Book

@{

    ViewBag.Title = "Details";

}

<h2>Details</h2>

    請注意第一行,標示着這個視圖是已經使用我們的Book類經過強類型化處理的。Razor視圖引擎會自動將其判定爲傳入了一個Book對象。這樣我們可以很輕鬆地訪問我們的模型類中的各個屬性,同時也可以使用Visual Studio編輯器中的智能代碼輸入功能。

    將<h2>標籤中內容修改爲如下所示的代碼,使其可以顯示傳入的Book對象的Title屬性中的內容。

<h2>書籍:@Model.Title</h2>

    請注意當你在@Model後面輸入點符號的時候會觸發智能代碼輸入功能,顯示Book類中的各個屬性。

    現在讓我們重新運行我們的應用程序,並訪問“/Store/Details/1”這個URL地址,瀏覽器中顯示結果如圖3-13所示。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-13 單本書籍信息展示畫面

    現在我們對Browse這個action方法做類似修改。首先修改方法使其返回一個ActionResult對象,然後修改方法內部代碼,創建一個新的Genre(書籍種類)對象,並將其傳入視圖,最後返回該視圖,代碼如下所示。

public ActionResult Browse(int id)

{

    String[] name=new string[3]{“小說”,”教材”,”科學”};

var genreModel = new Genre {ID=id,Name = name[id-1] };

    return View(genreModel);

}

    在Browse方法中點擊鼠標右鍵,然後點擊“添加視圖”菜單,然後追加一個強類型視圖,並且在模型類下拉框中選擇“Genre(MvcBookStore.Models)”,如圖3-14所示。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

3-14 添加書籍種類展示視圖

    更新視圖模板(Views文件夾下Store文件夾中的Browse.cshtml)中的代碼,使其顯示書籍種類信息,代碼如下所示。

@model MvcMusicStore.Models.Genre

@{

    ViewBag.Title = "書籍種類";

}

<h2>書籍種類: @Model.Name</h2>

    重新運行我們的應用程序,並訪問“/Store/Browse/1”這個URL地址,瀏覽器中顯示結果如圖3-15所示。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-15 書籍種類展示畫面

    最後,讓我們對StoreController控制器類中的Index這個action方法做一些稍爲複雜的修改,使其可以顯示由書店中所有書籍種類組成的列表。我們通過使用一個由我們的模型中的Genre對象所組成的列表(List)來實現這一功能,代碼如下所示。

public ActionResult Index()

{

    var genres = new List<Genre>

    {

        new Genre { ID=1,Name = "小說"},

        new Genre { ID=2, Name = "教材"},

        new Genre { ID=3,Name = "科學"}

    };

    return View(genres);

 }

    在Index方法中點擊鼠標右鍵,然後點擊“添加視圖”菜單,然後追加一個強類型視圖,並且在模型類下拉框中選擇“Genre(MvcBookStore.Models)”,在支架模板下拉框中選擇“List”,如圖3-16所示。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-16 添加書籍種類列表展示視圖

    點擊添加按鈕後打開自動創建的視圖文件,第一行中代碼標識着視圖中接收到了一個Genre對象所組成的集合。

@model IEnumerable<MvcMusicStore.Models.Genre>

    這行代碼告訴Razor視圖引擎將要處理一個存放了Genre對象所組成集合的模型(model)對象。這裏我們使用IEnumerable<Genre>,而不是使用List<Genre>,因爲前者更加通用,允許我們之後可以將視圖中所使用的模型類型修改爲其他任何支持Ienumerable接口的集合。

    接下來,我們書寫如下所示的代碼,對模型中的Genre對象所組成的集合進行一個遍歷。

@model IEnumerable<MvcMusicStore.Models.Genre>

@{

    ViewBag.Title = "挑選書籍";

}

<h3>書籍種類展示</h3>

<p>

    本書店共出售如下 @Model.Count() 種書籍:</p>

<ul>

    @foreach (var genre in Model)

    {

        <li>@genre.Name</li>

    }

</ul>

    請注意當書寫代碼時智能代碼輸入功能始終處於觸發狀態,例如當我們輸入“@Mode”之後編輯器自動顯示一個Genre類型的IEnumerable接口所支持的各種方法與屬性,如圖3-17所示。  

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-17 編輯器自動顯示一個Genre類型的IEnumerable接口所支持的各種方法與屬性

    在“foreach”循環中,Visual Web Developer能夠自動將每一個項目判定爲Genre類型,編輯器自動顯示Genre類型所支持的方法與屬性,如圖3-18所示。  

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-18編輯器自動顯示Genre類型所支持的方法與屬性

    請注意,在自動創建Genre類型的強類型化視圖的時候,能夠判別出來該類型有個Name屬性,並在進行遍歷的時候將該屬性內容寫出。同時自動生成Edit(編輯)鏈接,Details(數據詳細信息)鏈接與Delete(刪除)鏈接。在後文中我們將會針對編輯、刪除與數據詳細信息展示功能進行詳細介紹,這裏暫且略過。

    重新運行應用程序,並且訪問“/Store”URL地址,瀏覽器中顯示如圖3-19所示。

 

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

3-19 書籍種類列表畫面

3.5 追加頁面與頁面之間的鏈接

    現在我們的“/Store”這個URL地址所顯示的頁面中只是簡單地以文字的形式列舉出了各種書籍種類的名稱。接下來讓我們把此處的種類名稱修改爲可以鏈接到“/Store/Browse”這個URL地址,這樣的話當用戶點擊“小說”這個書籍種類的時候,頁面可以轉至“/Store/Browse/1”這個URL地址。

    更新Views文件夾下的Store文件夾中的Index.cshtml視圖中的代碼如下所示。

<ul>

    @foreach (var genre in Model)

    {

        <li><a href="/Store/Browse/@genre.ID">@genre.Name</a></li>

    }

</ul>

    這段代碼是有效的,但非常具有侷限性。例如,如果之後我們想改變控制器的名稱,我們還不得不修改此處的代碼。

    一種更好的書寫方法是藉助於一個HTML幫助器方法。在ASP.NET MVC的視圖中,可以使用HTML幫助器方法來實現大量類似於此的共通處理。Html.ActionLink()就是其中一個非常有用的HTML幫助器方法,它使得HTML中的<a>鏈接的書寫方法變得更加容易,同時可以確保鏈接中使用的URL路徑是正確的URL地址格式。

    Html.ActionLink()有幾個不同的重載方式,從而允許你在鏈接中指定任何所需要的信息。譬如在如下所示的簡單示例中,你可以指定鏈接文字以及當鏈接在客戶端被點擊時所執行的Action方法。例如,在代碼中,我們可以使用“鏈接到Store地址的Index方法”鏈接到StoreController控制器中的Index方法中。

@Html.ActionLink("鏈接到Store地址的Index方法", "Index")

    請注意,在這種情況下,我們不需要指定控制器的名稱,因爲我們只是鏈接到了使用當前視圖的控制器的另一個action方法中。

    鏈接到書籍種類展示頁面的時候還需要提供兩個參數,所以我們使用Html.ActionLink()方法的另一種重載方式,使其使用如下參數:

  1. 使用種類名稱作爲鏈接文字。
  2. 控制器中action方法的名稱(Browse)。
  3. 頁面參數,指定ID屬性的屬性名稱與屬性值。

    最終修改代碼如下所示:

<ul>

    @foreach (var genre in Model)

    {

        <li>@Html.ActionLink(genre.Name,"Browse", new {id=genre.ID})

</li>

    }

</ul>

    現在我們可以重新運行我們的應用程序,訪問“/Store”這個URL地址,我們可以看見一個所有書籍種類的列表展示頁面,如圖3-20所示。每一個種類都帶有一個超鏈接,點擊該超鏈接可以訪問“/Store/Browse/[書籍ID]”這個URL地址。

ASP.NET <wbr>MVC3書店--第三節 <wbr>視圖與視圖模型

圖3-20 所有書籍種類的列表展示頁面

    查看這個所有書籍種類的列表展示頁面的html源代碼,代碼如下所示。

<ul>

    <li><a href="/Store/Browse/1">小說</a></li>

    <li><a href="/Store/Browse/2">教材</a></li>

    <li><a href="/Store/Browse/3">科學</a></li>

</ul>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章