0.前言
在之前的幾篇中,我們大概介紹了如何創建一個asp.net core mvc專案以及http請求如何被路由轉交給對應的執行單元,這一篇我們將介紹一下控制器與視圖直接的關系,
1. 視圖
這里的視圖不是資料庫里的視圖,是一種展示技術,在asp.net core mvc專案中視圖是指以cshtml做擴展名的檔案,通常在Views檔案夾,
那么現在我們進到之前創建的測驗專案 MvcWeb的Views目錄下,如果小伙伴們沒有做修改的話,能看到如下的目錄結構:
├── Home
│ ├── Index.cshtml
│ └── Privacy.cshtml
├── Shared
│ ├── Error.cshtml
│ ├── _Layout.cshtml
│ └── _ValidationScriptsPartial.cshtml
├── _ViewImports.cshtml
└── _ViewStart.cshtml
在Views根目錄下,有兩個檔案分別是:_ViewImports.cshtml 、 _ViewStart.cshtml 兩個檔案(注意,有個前置下劃線),
1.1 在視圖中參考命名空間
我們知道,在cshtml檔案中,雖然極大的減少了服務器代碼,但是有時候無法避免的使用一些C#代碼,那么就會產生一個問題,很多類都有自己的命名空間,如果我們在某個或某幾個或某些視圖中需要訪問這些類和方法,那么一個視圖一個視圖的寫參考有點不太現實,因為這太繁瑣了,
所以asp.net core mvc 設定了在名為_ViewImports.cshtml的檔案中添加參考,則在Views下所有視圖中都生效,那么,先來看看這個檔案里有啥吧:
@using MvcWeb
@using MvcWeb.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
可以看到,這里參考了專案的命名空間和專案下Modes命名空間的所有內容,因為我們之前創建的測驗專案名稱就是 MvcWeb,
最后一行是一個 cshtml標記參考,第一個星號表示當前專案的所有TagHelper實作都參考,后面的表示引入aps.net core mvc內置的TagHelper,
關于 TagHelper,這篇就先不介紹了,
1.2 ViewsStart
_ViewStart.cshtml 作用從名字中可見一二,這個檔案用來配置一些在視圖剛開始加載時的一些配置內容,先看一下,默認的里面是什么吧:
@{
Layout = "_Layout";
}
先做個介紹,@符號后面用一對大括號包裹,里面是C# 代碼,也就是說 Layout = "_Layout",這行的意思是給某個名為Layout的屬性設定值為_Layout,
那么,Layout的屬性是哪里的呢?
對于asp.net core mvc而言,一個視圖也是一個類只不過這個類是動態生成的,不是一個由程式員撰寫出來的類,但是這個類繼承自:
namespace Microsoft.AspNetCore.Mvc.Razor
{
public abstract class RazorPageBase : IRazorPage
{
}
}
Layout正好是這個類的一個屬性,表示視圖是否使用了某個布局頁,所以上面的代碼表示,Views里的新建視圖,默認是使用名為_Layout的視圖作為布局頁,
當然,這個頁面不只有這個作用,小伙伴們可以自己嘗試下哦,
1.3 視圖檢索
在上一節中,我們指定了一個布局頁的名稱,布局頁也是視圖中的一種,但我們也只指定了名稱,但沒有指定路徑,asp.net core是如何發現這個名稱的視圖呢?
asp.net core 會按照以下順序查找對應的視圖檔案:
- Views/[ControllerName]/[ViewName].cshtml
- Views/Shared/[ViewName].cshtml
所以,_Layout也會按照這個順序查找,為了避免不必要的混淆,我們只在Shared目錄下寫了_Layout.cshtml,這也是通常的做法,該檔案表示一個全域的布局頁,
2. 控制器與視圖的關系
在上一篇《【asp.net core 系列】2 控制器與路由的恩怨情仇》中,我們介紹了三種創建控制器的方法,并且最后推薦使用名字以Controller結尾并繼承Controller類的寫法,我將在這里為大家再次講解為什么推薦這樣寫:
- 以Controller結尾,可以很明確的告訴其他人或者未來的自己這是一個控制器,不是別的類
- 繼承Controller,是因為Controller類為我們提供了控制器用到的屬性和方法
嗯,暫時就這兩點,別看少,但是這很重要,
2.1 使用視圖
在之前介紹的時候,有提到過當我們訪問一個URL的時候,路由會自動為我們尋找到對應的可執行代碼單元,但是,沒有進一步內容的介紹,當我們尋找到對應的可執行代碼單元也就是Action之后,Action進行一系列的處理,會對這個請求做出回應,有一種回應就是回傳一個展示頁面,也就是View,
那么,如何回傳一個View呢?
創建一個控制器,名為ViewDemoController,并添加一個方法Index,回傳型別為IActionResult:
using Microsoft.AspNetCore.Mvc;
namespace MvcWeb.Controllers
{
public class ViewDemoController:Controller
{
public IActionResult Index()
{
return View();
}
}
}
其中 View() 表示回傳一個View,這View的名稱是 Index,在ViewDemo控制器下,所以,它的路徑應該是:
Views/ViewDemo/Index.cshtml
在對應目錄創建該檔案,然后在檔案里隨便寫一些內容,之后啟動專案(專案的埠在第一部分就已經修改過了):
http://localhost:5006
然后訪問:
http://localhost:5006/ViewDemo/

應該是類似的頁面,
IActionResult 是一個介面,表示是一個Action的處理結果,在這里可以理解為固定寫法,
2.2 指定視圖
在控制器里,View 方法表示使用一個視圖進行渲染,默認是使用方法同名的視圖,當然,既然是默認的,那就一定有不默認的時候,對的,View方法提供了幾個多載版本,這些多載版本里有一個名字為viewName的引數,這個引數就是用來指定視圖名稱的,
那么,我們可以指定哪些視圖名稱:
- 同一個控制器檔案夾下的其他視圖
- Shared 檔案夾下的視圖
這兩種都是不用攜帶路徑的視圖名,可以省略檔案擴展名(cshtml),
當然,還可以指定其他路徑下的視圖檔案,如:
Views/Home/About.cshtml表示從根目錄下查找到這個視圖,這種寫法必須指定擴展名../Manage/Index表示在Manage控制器目錄下的Index
2.3 給視圖傳遞資料
之前介紹了如何使用視圖、如何指定視圖名稱,但是還缺最關鍵的一步,那就是如何給視圖傳遞資料,
通常情況下,Action方法中給視圖傳遞資料,只有這三種是推薦的:
- 使用ViewData
- 使用ViewDataAttribute
- 使用ViewBag
- 使用ViewModel
Controller類有一個屬性是 ViewData,它的宣告如下:
public ViewDataDictionary ViewData { get; set; }
可以看到這是一個字典型的屬性,所以給它賦值是這樣使用的:
public IActionResult Index()
{
ViewData["Title"] = "ViewDemo";
return View();
}
ViewBag也是 Controller類的一個屬性,它的宣告如下:
public dynamic ViewBag { get; }
可以看到這是一個動態類,實際上ViewBag里的資料與ViewData是互通的,換句話說就是ViewBag是對ViewData的一次封裝,兩者并沒有實際上的區別,賦值使用:
public IActionResult Index()
{
ViewBag.Name = "小李";
return View();
}
而ViewDataAttribute則與上兩個,不太一樣,這個屬性標注給控制器的屬性上,asp.net core mvc就會把這個屬性的值填充給ViewData,鍵值就是屬性名:
[ViewData]
public string AttributeTest{get;set;}
與 ViewData["AttributeTest"]效果一致,
在View方法的一些多載版本里,需要一個名為 model的引數,型別是object,這個引數就是一個ViewModel,使用:
在MvcWeb/Models 下添加一個類:
namespace MvcWeb.Models
{
public class ViewModelTestModel
{
public string Name{get;set;}
public int Age{get;set;}
}
}
回到剛剛的Index方法里,創建一個ViewModelTestModel實體,并傳給View方法:
public IActionResult Index()
{
ViewData["Title"] = "ViewDemo";
ViewBag.Name = "小李";
var model = new ViewModelTestModel
{
Name = "測驗實體",
Age = 1
};
return View(model);
}
2.4 在視圖中使用
在上一小節中,我們分別使用ViewData和ViewBag以及ViewModel給視圖傳遞了三個資料,那么如何在視圖中獲取這三個資料呢?
<h2>@ViewData["Title"]</h2>
<!--實際會顯示 <h2>ViewDemo</h2>-->
與字典一樣,@起頭,表示后面跟著一個屬性或者一段C#運算式,并將運算式的結果輸出到頁面上,
ViewBag的訪問與ViewData類似,只不過ViewBag是動態物件,可以認為它的型別并沒有發生改變,繼續按照之前的型別進行使用:
<h4>@ViewBag.Name</h4>
對于ViewModel的使用,View內置了一個dynamic的Model屬性,在不做特殊處理的情況下,我們在頁面上使用@Model 會得到一個dynamic物件(如果傳了ViewModel的話),雖然也能用,但是這不太友好,
這時候,就需要我們在視圖的開頭處,添加:
@model ViewModelTestModel
這時候,再使用@Model的時候,就會自動決議成ViewModelTestModel了,
整體Index.cshtml內容如下:
@model ViewModelTestModel
Hello World!
<h2>@ViewData["Title"]</h2>
<h4>@ViewBag.Name</h4>
@Model.Name + @Model.Age
然后重啟服務后,重繪頁面,會看到類似的內容:

3. 總結
我們在這一篇介紹了視圖的一些概念,并介紹了如何使用控制器給視圖傳遞資料,下一篇將講解一下路由的高級作用,如何通過路由攜帶資料,
更多內容煩請關注我的博客《高先生小屋》

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/26995.html
標籤:C#
上一篇:二叉樹遍歷
