[鐵人賽Day12] ASP.Net Core MVC 進化之路 - View(2) / Tag Helper及Layout

本篇將針對View中Tag HelperLayout進行介紹。

 

TagHelper

ASP.Net MVC5中我們可以透過Html Helper產生HTML,

而在ASP.Net Core中多了一個新選擇 - TagHeper

現在我們可以將參數直接內嵌在HTML Tag裡(跟某些前端Framework很像)。

 

舉常見的LabelForEditorFor為例,

使用Html Helper

<div class="form-group">
    @Html.LabelFor(model => model.Property, new { @class="control-label" })
    @Html.EditorFor(model => model.Property, new { htmlAttributes = new{ @class="form-control"}})
    @Html.ValidationMessageFor(model => model.Property, "", new { @class="text-danger" })
</div>

使用Tag Helper

<div class="form-group">
    <label asp-for="Property" class="control-label"></label>
    <input asp-for="Property" class="form-control" />
    <span asp-validation-for="Property" class="text-danger"></span>
</div>

 

Tag Helper使用方式比起Html Helper更加直覺,

只要在HTML Tag中宣告asp-for即可使用,

但這裡的for代表的並不是迴圈,

而是Model Binding綁定的對象。

也因為語法更貼近原始的HTML Tag,

因此也更方便前端工程師修改。

可使用的種類也與Html Helper大致相同。

 

還記得MVC5中的Ajax Helper嗎?

在ASP.Net MVC5中可以透過@Ajax.BeginForm()進行Ajax操作,

不過ASP.Net Core中則移除了Ajax Helper。

若想要使用原本Ajax Helper提供的功能,

可透過data-attributes操作原生的jquery.unobtrusive-ajax(參考連結)。

 

另外原本用來防止CSRF的@Html.AntiForgeryToken()

在ASP.Net Core中只要form標籤中含有asp-開頭的tag,

就會自動產生防止的token。

 

關於Tag Helper的種類可以參考Microsoft.AspNetCore.Mvc.TagHelpers

 

Layout

一般在設計網站時會使用相同的版面風格進行設計,

可簡單拆為幾個部分:

  • Header:設定網頁標題、載入Resource(如css)等。
  • Navigation Menu Bar/Side Bar (功能列表):通常位於上/左/右其中一方。
  • Content:實際放置網頁內容。
  • Footer:網頁下欄,也可放置資源檔(.js)

 

在ASP.Net Core MVC中,

版面配置這塊並沒有太大的改變。

我們可以在專案目錄/View/Shared中找到_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - IronmenMvcWeb</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-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">IronmenMvcWeb</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2018 - IronmenMvcWeb</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>

 

其中 <environment>可根據目前的環境呈現內容,

區分includeexclude兩種模式(ASP.NET Core 2.0版本後),

可填入參數為有StagingDevelopment 、Production

 

View Engine在將View轉譯為HTML

會將轉譯後的HTML塞到<body>中的@RenderBody

使用@RenderSection("Scripts", required: false)可自訂特定區段位置,

透過required屬性可設定套用此Layout的View是否一定要呼叫該區段。

我們可以在View中使用@section scripts{ ... }進行叫用,

View Engine會幫我們將@section中的內容填入Layout中@RenderSection的位置。

 

而筆者個人在專案中會習慣在<head>中加上一個@RenderSection("Styles", required: false)

可以幫助我們將網頁上的javascript或css集中到某個區段。

 

最後介紹View資料夾底下的兩個檔案:

  • _ViewImports.cshtml
  • _ViewStart.cshtml

 

_ViewImports.cshtml預設會放在View資料夾底下,

它可以用來宣告許多View通用的指令

如命名空間、加入Tag Helper、設定DI等等。

_ViewImports.cshtml可以同時存在於多個View底下的目錄,

它會將自身宣告的指令套用在子目錄中的View身上,

當遇到相同指令時以最內層的指令進行override。

 

_ViewStart.cshtml_ViewImports.cshtml功能相似,

它會在每個View起始階段執行,

地位有如程式類別(Class)中的建構子(Constructor)。

_ViewStart.cshtml也可同時存在於View及View/{ControllerName}底下的目錄,

同時存在時會由外到內執行。

 

本篇就介紹到這邊,

下一篇會針對Partial ViewView Component做介紹。

 

參考

https://docs.microsoft.com/zh-tw/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-2.1

https://docs.microsoft.com/zh-tw/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1

https://docs.microsoft.com/zh-tw/aspnet/core/mvc/views/layout?view=aspnetcore-2.1

https://docs.microsoft.com/zh-tw/aspnet/core/mvc/views/tag-helpers/built-in/environment-tag-helper?view=aspnetcore-2.1