Razor Page入門 - 1

by vivid 13. 五月 2020 10:48

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N200521901
出刊日期: 2020/5/13

ASP.NET Core Razor Page為ASP.NET Core MVC的一部分,需ASP.NET Core 2.0 以上版本才可以使用。開發的方式較類似MVVM Framework(Model-View-ViewModel Framework),支援雙向資料繫結的能力,將控制器與動作內建在PageModel之中,容易學習,適用於簡單、唯讀、只做簡單資料輸入的網頁。

這篇文章中將讓您瞭解如何在Visual Studio 2019開發環境中新建一個ASP.NET Core Razor Page網站應用程式。有別於ASP.NET Core MVC使用模型檢視控制器(Model-View-Controller,MVC)的設計模式,ASP.NET Core Razor Page專注在頁面(Page)的設計情境,更容易使用,也更具生產力,透過這篇文章來了解如何建立一個跨平台的ASP.NET Core Razor Page網站應用程式。

建立Razor Page專案

啟動Visual Studio 2019開發環境,從「開始」視窗選取「Create a new project」選項,請參考下圖所示:

clip_image002

圖 1:「Create a new project」選項。

從開發工具「Create a new project」對話盒中,選取「ASP.NET Core Web Application」項目,請參考下圖所示:

clip_image004

圖 2:選取「ASP.NET Core Web Application」項目。

在「Configure your new project」視窗中設定專案名稱為「MyRazorWeb」,設定專案存放路徑,然後按下「Create」鍵,請參考下圖所示:

clip_image006

圖 3:「Configure your new project」視窗。

在「Create a new ASP.NET Core web application」視窗,確認左上方的清單選取「.NET Core」,右上方的清單ASP.NET Core版本為「ASP.NET Core 3.x」,選取下方的「Web Application」樣版專案,清除勾選下方的「Enable Docker Support」核取方塊,確定右方的「Authentication」項目設定為「No Authentication」,勾選右下方的「Configure for HTTPS」核取方塊,然後按下「Create」按鈕建立專案,請參考下圖所示:

clip_image008

圖 4:「Create a new ASP.NET Core web application」範本。

專案建立之後,檢視「Solution Explorer」視窗,檔案結構大致如下圖所示:

clip_image010

圖 5:Razor Page檔案結構。

Razor Page專案檔案與資料夾說明如下:

l 「wwwroot」資料夾:存放靜態檔案。

l 「Pages」資料夾:存放Razor Page相關檔案。

l 「appsettings.json」檔案:應用程式組態檔案。

l 「Program.cs」檔案:用來進行裝載程式設定。

l 「Startup.cs」檔案:用來設定服務與請求管線。

預設專案「Pages」資料夾中將會產生一個Index.cshtml檔案,與一個Index.cshtml.cs檔案,這是網站首頁的程式碼,「*.cshtml」檔案用來定義網頁顯示的樣版,而「*.cs」檔案中定義「PageModel」。讓我們先來編譯這個專案,選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯,結果看起來如下圖所示:。

clip_image012

圖 6:編譯專案。

在Visual Studio開發工具,按CTRL+F5執行網站,執行結果參考如下圖所示:

clip_image014

圖 7:Razor Page網站。

預設Razor Page的路由對應到cshtml檔案的名稱,在瀏覽器輸入以下網址(URL),注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號):

https://localhost:44300/Index

同樣會看到首頁的內容,若輸入以下網址(URL),便會看到「Privacy.cshtml」執行的結果:

https://localhost:44300/Privacy

了解Razor Page

Razor Page網頁要放在專案「Pages」資料夾中,Razor Page通常包含兩個檔案,其中「*.cshtml」檔案用來定義網頁顯示樣版(Display Template),其中包含HTML與Razor語法,而「*.cs」檔案中定義「PageModel」類別,我們可以看一下範本專案中建立的「Index.cshtml」與「Index.cshtml.cs」檔案內容如下:

Index.cshtml

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

預設「Index.cshtml.cs」檔案中將包含以下程式碼,包含一個名為「IndexModel」的「PageModel」類別:

  • Index.cshtml.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace MyRazorWeb.Pages {
  public class IndexModel : PageModel {
    private readonly ILogger<IndexModel> _logger;

    public IndexModel( ILogger<IndexModel> logger ) {
      _logger = logger;
    }

    public void OnGet() {

    }
  }
}

 

「Index.cshtml」檔案中的第一行必需是「@page」指示詞,表明這個檔案是Razor Page,以有别於MVC專案中的cshtml檔案。它會將檔案轉換成MVC動作(Action),不需要額外再撰寫控制器,就可以直接處理HTTP請求。「@model指示詞指明PageModel,對應到「Index.cshtml.cs」檔案中的類別名稱。

PageModel類別中包含了伺服端執行的C#程式碼,根據慣例PageModel類別的命名規則是「頁面名稱+Model」(<PageName>Model),因此「Index」對應的PageModel名稱為「IndexModel」。PageModel要繼承「PageModel」類別。同時,Razor Page支援相依性插入(Dependency Injection),因此「IndexModel」建構函式中,插入內建的「ILogger」服務以用來產生除錯資訊。

在PageModel中可以定義「處理常式方法(Handler Method)」,常見的處理常式方法包含:

l OnGet:撰寫初始化頁面所需的程式碼。

l OnPost:用來處理表單提交的動作。

讓我們來修改一下PageModel程式碼,為「IndexModel」加上一個字串型別的公開屬性「Greeting」,以讓顯示樣版可以存取,並在「OnGet」方法中回傳「Hello World !」字串。

Index.cshtml.cs

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace MyRazorWeb.Pages {
  public class IndexModel : PageModel {
    private readonly ILogger<IndexModel> _logger;

    public string Greeting { get; set; }
    public IndexModel( ILogger<IndexModel> logger ) {
      _logger = logger;
    }

    public void OnGet() {
      Greeting = " Hello World !";
    }
  }
}

修改「Index.cshtml」檔案,使用「@Model.Greeting」語法存取PageModel類別中的「Greeting」屬性:

Index.cshtml

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">@Model.Greeting</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>


選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站,執行結果參考如下圖所示,畫面將顯示「Hello World !」歡迎訊息:

clip_image016

圖 8:使用PageModel屬性。

從這個範例中,我們了解到Razor Page包含顯示樣版(*.cshtml,Display Template)與PageModel類別,PageModel類別類似MVC架構中的控制器(Controller)加模型(Model),PageModel類別中「OnGet」方法就類似MVC架構中控制器的動作(Action);PageModel類別中的public屬性,類似MVC架構中的模型(Model)。顯示樣版(*.cshtml,Display Template)之中包含HTML,它則類似MVC架構中的檢視(View)。

Razor版面配置(Razor Layout)

一般網站的多個頁面,都具有共同的區塊,像是選單、版權宣告說明、表頭、表尾...等等。ASP.NET Core Razor Page的版面配置(Razor Layout)為整個網站建立樣式樣版(Style Template),確保Razor 頁面(Razor Page)有一致的外觀,只要定義好Razor版面配置(Razor Layout),便可以在多個Razor 頁面(Razor Page)之間共用。

Razor 檢視引擎(Razor view engine)提供的以下功能都適用於Razor 頁面(Razor Page)

• Razor版面配置(Razor Layout)。

• 部分檢視 (Partials)。

• 標記協助程式(Tag Helper)。

• _ViewStart.cshtml。

• _ViewImports.cshtml 。

接下來將介紹瞭解如何使用「_ViewStart.cshtml」以及Razor版面配置(Razor Layout)來設計網站共用的版面。

定義Razor版面配置(Razor Layout)

Razor版面配置(Razor Layout)通常會包含網頁共用的內容,包含HTML、CSS….等。習慣檔案的名稱以 _(底線) 開始命名,檢視目前建立的範例網站,在「Pages/Shared」資料夾之中包含一個「_Layout.cshtml」檔案,其定義如下列所示,在Razor Page中,Razor版面配置(Razor Layout)要放在 「Pages」資料夾之中,頁面搜尋時會根據資料夾來查找。Razor版面配置(Razor Layout)不建議放在「Views/Shared」資料夾中,此資料夾只適用於MVC網站開發模式。

_Layout.cshtml

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - MyRazorWeb</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">MyRazorWeb</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2020 - MyRazorWeb - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

預設ASP.NET Core不處理靜態資源檔案,如JavaScript、CSS、圖片等等檔案,這些檔案要放在專案根目錄下「wwwroot」資料夾之中。在「Startup.cs」檔案中的Configure方法內,包含一行程式碼「app.UseStaticFiles();」透過內建的中介軟體(middleware)來處理這些靜態資源檔案的請求。

@ViewData["Title"]

「@」符號開頭的程式是Razor語法,「@」符號後是C#程式碼,單獨寫成一行時,不必使用「;」號結尾。我們可以看到<head>標籤之中包含一行程式碼,使用「@ViewData["Title"]」讀取網頁的表頭:

<title>@ViewData["Title"] - MyRazorWeb</title>

以「Index.cshtml」檔案為例,ViewData["Title"]的值是透過「Index.cshtml」檔案中的「ViewData["Title"] = "Home page"」這行程式碼設定的,參考以下程式碼:

Index.cshtml

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">@Model.Greeting</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

 

Razor語法中多行程式碼區塊需使用「@{ }」包起來,其中可以混雜出現C#程式碼、HTML、靜態文字,每行C#程式碼記得要以「;」號結尾。

當「Index.cshtml」網頁執行時,便可以在網頁上方看到標題,請參考下圖所示:

clip_image018

圖 9:「Index.cshtml」網頁執行結果。

設計導覽選單

「_Layout.cshtml」Razor版面配置(Razor Layout)檔案中包含以下<nav>標籤,用來定義選單,標籤中套用許多CSS類別,如「navbar」、「container」等等,這些是來自Bootstrap 4套件,以設計出符合響應式網頁(Responsive Web Design)設計風格的網站。

<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
    <div class="container">
        <a class="navbar-brand" asp-area="" asp-page="/Index">MyRazorWeb</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
            <ul class="navbar-nav flex-grow-1">
                <li class="nav-item">
                    <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

 

RWD是一種網頁設計方式。讓同一個網頁無論在是傳統的桌上型環境,或是現在最流行的智慧型手機,都可以適當呈現網頁內容。RWD的重點在於如何對目標的裝置排列內容。像桌上型的瀏覽器,比較適合水平排列內容。在技術上,如果要實踐RWD,可以使用CSS3的Media Query技術來達成。

「Bootstrap」是當前非常熱門的一個前端網頁開發使用的框架(Framework)。對於不太擅長JavaScript、CSS的開發人員,又要負責建立同時適合不同裝置上,使用瀏覽器都可以適當呈現的頁面,提供了一個解決方案,「Bootstrap」底層使用Media Query以達到響應式網頁的需求,你不需要學會Media Query也可以使用Bootstrap。

使用桌上型的瀏覽器來檢視網站首頁,選單會呈現出水平排列內容,請參考下圖所示:

clip_image020

圖 10:RWD風格網頁--桌上型的瀏覽器顯示效果。

而在行動裝置上,則會自動切換成比較適合以堆疊的方式排列內容,請參考下圖所示:

clip_image022

圖 11:RWD風格網頁--行動裝置的瀏覽器顯示效果。

<nav>標籤中使用到「asp-area」與「asp-page」標記協助程式(Tag Helper),用於產生<a>標籤「href」attribute,以跳到特定的頁面:

<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>

網頁執行之後,搭配這些標記協助程式(Tag Helper)產生的<a>標籤內容如下:

<a class="nav-link text-dark" href="/">Home</a>

而以下這段程式:

<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>

產生的<a>標籤內容如下:

<a class="nav-link text-dark" href="/Privacy">Privacy</a>

asp-append-version標記協助程式(Tag Helper)

「_Layout.cshtml」Razor版面配置(Razor Layout)檔案中包含以下<script>區段,套用了「asp-append-version標記協助程式(Tag Helper):

<script src="~/js/site.js" asp-append-version="true"></script>

「asp-append-version」設為「true」會附加查詢字串「v」,可以檢視瀏覽器收到的HTML如下:

<script src="/js/site.js?v=dLGP40S79Xnx6GqUthRF6NWvjvhQ1nOvdVSwaNcgG18"> </script>

它的值是從檔案內容計算而來的,檔案內容若變動,這個值就會不同,若查詢字串的內容變動,瀏覽器就會從伺服器取得新版本,以避免瀏覽器載入本機快取(Cache)中的舊檔案來執行。

@RenderBody()

在「_Layout.cshtml」Razor版面配置(Razor Layout)檔案中「@RenderBody()」 這行程式碼出現的位置就是Razor頁面(Razor Page)插入的位置:

<div class="container">
      <main role="main" class="pb-3">
          @RenderBody()
      </main>
  </div>

 

一個套用Razor版面配置(Razor Layout)的Razor Page可以定義多個區段(Section),區段(Section)可以是強制性或是選擇性的。在「_Layout.cshtml」Razor版面配置(Razor Layout)檔案中</body>標籤之上,可以看到這行程式碼:

@RenderSection("Scripts", required: false)

Razor頁面(Razor Page)中定義的「Scripts」區段,將會插入「RenderSection("Scripts", required: false)」這行程式碼出現的位置。「required」設為「false」表示其為選擇性的,我們試著改為「true」:

@RenderSection("Scripts", required: true)

「Index.cshtml」執行的結果請參考下圖所示,將得到一個例外錯誤:「An unhandled exception occurred while processing the request.」:

clip_image024

圖 12:未定義區段(Section)例外錯誤。

顧名思義,預設範本專案中「Scripts」區段用來插入要引用的JavaScript程式碼。為了簡單說明起見,我們故意在「Index.cshtml」之中加入一個「Scripts」區段,只顯示伺服端系統時間:

Index.cshtml

@section scripts{
    <div class="text-center">
        <p>Server Time is @DateTime.Now.ToLongDateString()</p>
    </div>
}

 

「Index.cshtml」執行的結果請參考下圖所示:

clip_image026

圖 13:使用區段。

Visual Studio 2019開發工具支援

最後我們來看看Visual Studio 2019開發工具對於定義Razor版面配置(Razor Layout)的支援,在「Pages」資料夾下加入一個「Books」資料夾。從「Solution Explorer」視窗 「Pages」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Folder」選項,請參考下圖所示:

clip_image028

圖 14:加入一個「Books」資料夾。

從「Solution Explorer」視窗 「Books」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「Razor Page」選項,請參考下圖所示:

clip_image030

圖 15:加入「Razor Page」。

在「Add New Scaffolded Item」對話盒中選取「Razor Page」項目,請參考下圖所示:

clip_image032

圖 16:選取「Razor Page」。

「Add Razor Page」對話盒中,設定「Razor Page name」設定為「List」,勾選下方「Generate PageModel class」,與「Use a layout page:」,最後按下「Add」按鈕,請參考下圖所示:

clip_image034

圖 17:套用Razor Layout。

預設「List.cshtml」檔案中將包含以下程式碼:

List.cshtml

 

@page
@model MyRazorWeb.ListModel
@{
    ViewData["Title"] = "List";
}

<h1>List</h1>


網站執行之前,記得先將「_Layout.cshtml」檔案中「required」屬性設定為「false」:

@RenderSection("Scripts", required: false)

選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下網址(URL):

https://localhost:44300/Books/List

執行結果參考如下,畫面將顯示套用Razor版面配置(Razor Layout)的「List.cshtml」執行結果:

clip_image036

圖 18:套用Razor 版面配置。

最後讓我們修改一下Razor版面配置(Razor Layout)「_Layout.cshtml」檔案,加入超連結,以導向「Books/List」:

<li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-page="/Books/List">Books</a>
</li>

 

「_Layout.cshtml」檔案內容看起來如下:

_Layout.cshtml

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - MyRazorWeb</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">MyRazorWeb</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Books/List">Books</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2020 - MyRazorWeb - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

 

選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站首頁,執行結果請參考下圖所示:

clip_image038

圖 19:加入導覽功能。

Tags:

ASP.NET Razor Pages | .NET Magazine國際中文電子雜誌 | .NET Core | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List