ASP.NET Core 中的配置

作者:Steve SmithDave Brock

頁面和檢視經常會共用視覺效果和程式設計項目。 本文會示範如何:

  • 使用常見配置。
  • 共用指示詞。
  • 執行常見的程式碼,再轉譯頁面或檢視。

本文件將探討 ASP.NET Core MVC 兩種不同方法的配置:Razor Pages 和包含檢視的控制器。 針對本主題,差異很小:

  • Razor Pages 位於 Pages 資料夾。
  • 包含檢視的控制器,使用 Views 資料夾進行檢視。

何謂配置

大部分的 Web 應用程式都會有通用配置,可提供使用者一致的巡覽頁面體驗。 配置通常會包括一般使用者介面項目,例如應用程式標頭、導覽或功能表項目,以及頁尾。

Page Layout example

在應用程式內,有許多頁面經常會使用通用 HTML 結構,例如指令碼和樣式表。 所有這些共用項目可能都定義在 layout 檔案中,而之後應用程式內使用的任何檢視都可以參考該檔案。 版面配置會減少檢視中重複的程式碼。

依照慣例,ASP.NET Core 應用程式的預設配置命名為 _Layout.cshtml。 使用範本建立的新 ASP.NET Core 專案配置檔案為:

  • Razor Pages:Pages/Shared/_Layout.cshtml

    Pages folder in Solution Explorer

  • 具有檢視的控制器:Views/Shared/_Layout.cshtml

    Views folder in Solution Explorer

此配置會定義應用程式中檢視的最上層範本。 應用程式不需要版面配置。 應用程式可以定義多個配置,並以不同檢視指定不同的版面配置。

下列程式碼顯示使用範本建立之專案 (包含控制器和檢視) 的配置檔案:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication1</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">WebApplication1</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-page="/Index">Home</a></li>
                    <li><a asp-page="/About">About</a></li>
                    <li><a asp-page="/Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2018 - WebApplication1</p>
        </footer>
    </div>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
        </script>
        <script src="~/js/site.min.js" asp-append-version="true"></script>
    </environment>

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

指定配置

Razor 檢視具有 Layout 屬性。 個別檢視透過設定此屬性來指定配置:

@{
    Layout = "_Layout";
}

指定的配置可以使用完整路徑 (例如 /Pages/Shared/_Layout.cshtml/Views/Shared/_Layout.cshtml) 或部分名稱 (範例:_Layout)。 提供部分名稱時,Razor 檢視引擎會使用其標準探索程序來搜尋配置檔案。 首先搜尋處理常式方法 (或控制器) 所在的資料夾,接著搜尋 Shared 資料夾。 此探索程序相當於用來探索部分檢視的程序。

根據預設,每個配置都必須呼叫 RenderBody。 不論在何處呼叫 RenderBody,都會轉譯檢視內容。

區段

配置可以選擇性地呼叫 RenderSection,以參考一或多個「區段」。 區段提供一種方式,來組織特定頁面項目應放置的位置。 每次呼叫 RenderSection,都可以指定該區段是必要區段或是選擇性區段:

<script type="text/javascript" src="~/scripts/global.js"></script>

@RenderSection("Scripts", required: false)

如果找不到必要區段,將會擲回例外狀況。 個別檢視指定要使用 @sectionRazor 語法在區段內轉譯的內容。 如果頁面或檢視定義區段,則必須進行轉譯 (否則會發生錯誤)。

Razor Pages 檢視中的範例 @section 定義:

@section Scripts {
     <script type="text/javascript" src="~/scripts/main.js"></script>
}

在上述程式碼中,scripts/main.js 會新增至頁面或檢視上的 scripts 區段。 相同應用程式中的其他頁面或檢視可能不需要此指令碼,也不會定義指令碼區段。

下列標記會使用部分標籤協助程式來轉譯 _ValidationScriptsPartial.cshtml

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

前述標記由 scaffolding Identity 產生。

頁面或檢視中所定義的區段僅適用於其立即配置頁面。 無法從部分、檢視元件或檢視系統的其他部分參考它們。

忽略區段

根據預設,內容頁面中的本文和所有區段都必須透過配置頁面進行轉譯。 Razor 檢視引擎會強制執行此作業,方法是追蹤是否已轉譯本文和每個區段。

若要指示檢視引擎略過本文或區段,請呼叫 IgnoreBodyIgnoreSection 方法。

Razor 頁面中的本文和每個區段都必須進行轉譯或忽略。

匯入共用指示詞

檢視和頁面可以使用 Razor 指示詞匯入命名空間,並使用相依性插入。 許多檢視所共用的指示詞可能指定於通用 _ViewImports.cshtml 檔案中。 _ViewImports 檔案支援下列指示詞:

  • @addTagHelper
  • @removeTagHelper
  • @tagHelperPrefix
  • @using
  • @model
  • @inherits
  • @inject
  • @namespace

檔案不支援其他 Razor 功能,例如函式和區段定義。

範例 _ViewImports.cshtml 檔案:

@using WebApplication1
@using WebApplication1.Models
@using WebApplication1.Models.AccountViewModels
@using WebApplication1.Models.ManageViewModels
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

ASP.NET Core MVC 應用程式的 _ViewImports.cshtml 檔案通常會放在 Pages (或 Views) 資料夾中。 _ViewImports.cshtml 檔案可以放在任何資料夾內;在此情況下,它只會套用至該資料夾和其子資料夾內的頁面或檢視。 _ViewImports 檔案會從根層級開始處理,然後處理導向頁面或檢視本身位置的每個資料夾。 根層級指定的 _ViewImports 設定可以在資料夾層級覆寫。

例如,假設:

  • 根層級的 _ViewImports.cshtml 檔案包含 @model MyModel1@addTagHelper *, MyTagHelper1
  • 子資料夾 _ViewImports.cshtml 檔案包含 @model MyModel2@addTagHelper *, MyTagHelper2

子資料夾中的頁面和檢視可以存取標籤協助程式和 MyModel2 模型。

如果在檔案階層有多個 _ViewImports.cshtml 檔案,指示詞的合併行為是:

  • @addTagHelper@removeTagHelper:全部依序執行
  • @tagHelperPrefix:最接近檢視的項目會覆寫任何其他項目
  • @model:最接近檢視的項目會覆寫任何其他項目
  • @inherits:最接近檢視的項目會覆寫任何其他項目
  • @using:全部包括,但忽略重複項目
  • @inject:針對每個屬性,最接近檢視的項目會覆寫任何其他具有相同屬性名稱的項目

在每個檢視之前執行程式碼

需要在每個檢視或頁面之前執行的程式碼應放在_ViewStart.cshtml 檔案中。 依照慣例,_ViewStart.cshtml 檔案會位於 Pages (或 Views) 資料夾中。 _ViewStart.cshtml 中所列的陳述式會在每個完整檢視之前執行 (不是配置,也不是部分檢視)。 與 ViewImports.cshtml 類似,_ViewStart.cshtml 是階層式的。 如果 _ViewStart.cshtml 檔案是定義於檢視或頁面資料夾中,則會在 Pages (或 Views) 資料夾 (如果有的話) 根目錄中所定義的檔案後面執行。

範例 _ViewStart.cshtml 檔案:

@{
    Layout = "_Layout";
}

上面的檔案指定所有檢視都會使用 _Layout.cshtml 配置。

_ViewStart.cshtml_ViewImports.cshtml 通常不會放在 /Pages/Shared (或 /Views/Shared) 資料夾中。 這些檔案的應用程式層級版本應該直接放在 /Pages (或 /Views) 資料夾中。