本篇將針對View中Tag Helper及Layout進行介紹。
TagHelper
在ASP.Net MVC5中我們可以透過Html Helper產生HTML,
而在ASP.Net Core中多了一個新選擇 - TagHeper。
現在我們可以將參數直接內嵌在HTML Tag裡(跟某些前端Framework很像)。
舉常見的LabelFor跟EditorFor為例,
使用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.
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>© 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>
可根據目前的環境呈現內容,
區分include
及exclude
兩種模式(ASP.NET Core 2.0版本後),
可填入參數為有Staging、Development 、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 View及View 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