天天看點

【asp.net core 系列】3 視圖以及視圖與控制器

【asp.net core 系列】3 視圖以及視圖與控制器

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。這也是通常的做法,該檔案表示一個全局的布局頁。

  1. 控制器與視圖的關系

    在上一篇《【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的一次封裝,兩者并沒有實際上的差別。指派使用:

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方法:

ViewData["Title"] = "ViewDemo";
ViewBag.Name = "小李";
var model = new ViewModelTestModel
{
    Name = "測試執行個體",
    Age = 1
};
return View(model);           

2.4 在視圖中使用

在上一小節中,我們分别使用ViewData和ViewBag以及ViewModel給視圖傳遞了三個資料,那麼如何在視圖中擷取這三個資料呢?

@ViewData["Title"]

與字典一樣,@起頭,表示後面跟着一個屬性或者一段C#表達式,并将表達式的結果輸出到頁面上。

ViewBag的通路與ViewData類似,隻不過ViewBag是動态對象,可以認為它的類型并沒有發生改變,繼續按照之前的類型進行使用:

@ViewBag.Name

對于ViewModel的使用,View内置了一個dynamic的Model屬性,在不做特殊處理的情況下,我們在頁面上使用@Model 會得到一個dynamic對象(如果傳了ViewModel的話)。雖然也能用,但是這不太友好。

這時候,就需要我們在視圖的開頭處,添加:

@model ViewModelTestModel

這時候,再使用@Model的時候,就會自動解析成ViewModelTestModel了。

整體Index.cshtml内容如下:

Hello World!

@Model.Name + @Model.Age

然後重新開機服務後,重新整理頁面,會看到類似的内容:

  1. 總結

    我們在這一篇介紹了視圖的一些概念,并介紹了如何使用控制器給視圖傳遞資料。下一篇将講解一下路由的進階作用,如何通過路由攜帶資料。

原文位址

https://www.cnblogs.com/c7jie/p/13034221.html

繼續閱讀