前言
因為公司內部許多程式都只能用 IE 開啟,但隨著作業系統更新至 Win 10 or Win 11 已經開始不支援 IE 所以要開始著手翻舊系統,而新系統架構選擇用 .Net Core 6 MVC ,藉由這次過程學習 Visual Studio & Resharper & C# & Razor 📖
🔖 文章索引
1. 依環境載入 Vue.js
2. 使用 ViewBag 將資料向下傳遞
3. _Layout.cshtml 設定每個頁面獨立加 style & script
4. 各別頁面使用不同 Layout
5. 各別資料夾下的頁面使用同個 Layout
6. 防止 js/css/圖檔舊版 Cache 搗亂
7. Vue Demo
8. Sweet Alert 2 Demo
依環境載入 Vue.js
Vue.js 有分開發版本 ( vue.global.js ) 和上線版本 ( vue.global.prod.js )
當環境是 Production
就要載入上線版本 ( vue.global.prod.js )
@* /Views/Shared/_Layout.cshtml *@
@{
var CurrentEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
}
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
@RenderBody()
@if( CurrentEnvironment == "Production" )
{
<partial name="_ProdScript" />
}
else
{
<partial name="_DevScript" />
}
</body>
</html>
@* /Views/Shared/_DevScript.cshtml *@
<script src="~/js/chunk-vendors.js"></script>
<script src="~/js/vue.dev.js"></script>
@* /Views/Shared/_ProdScript.cshtml *@
<script src="~/js/chunk-vendors.js"></script>
<script src="~/js/vue.prod.js"></script>
使用 ViewBag 將資料向下傳遞
依照 @{ var CurrentEnvironment = ... }
的宣告方式只能在同一頁面使用這個變數,如果今天想要讓 <partial name="..." />
頁面內容取得變數就需改用 ViewBag.CurrentEnvironment
的宣告方式
調整 _Layout.cshtml
@* /Views/Shared/_Layout.cshtml *@
@{
// 建議將這段宣告在 /Views/_ViewStart.cshtml
ViewBag.CurrentEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
}
<!DOCTYPE html>
<html lang="en">
<head>
@*
5 ways to render a partial view in asp.net core
https://nitishkaushik.com/how-to-render-a-partial-view-in-asp-net-core/
*@
<partial name="_Head" />
@await RenderSectionAsync("AdditionalCSS", required: false)
</head>
<body>
@RenderBody()
<partial name="_Script"/>
@await RenderSectionAsync("AdditionalScript", required: false)
</body>
</html>
將 _DevScript.cshtml
& _ProdScript.cshtml
合併為 _Script.cshtml
@* /Views/Shared/_Script.cshtml *@
<script src="~/js/chunk-vendors.js"></script>
@if (ViewBag.CurrentEnvironment == "Production")
{
<script src="~/js/vue.prod.js"></script>
}
else
{
<script src="~/js/vue.dev.js"></script>
}
Note: @RenderBody()
的頁面 ( EX: /Views/Home/Index.cshtml
) 是吃不到 ViewBag.CurrentEnvironment
但是 /Views/Home/Index.cshtml
上方宣告 @{ ViewBag.Title = "首頁"; }
卻可以讓 /Views/Shared/_Layout.cshtml
的 <partial name="_Head" />
取得值
要解決讓 /Views/Home/Index.cshtml
也可以吃到 ViewBag.CurrentEnvironment
就要將原本在 /Views/Shared/_Layout.cshtml
的宣告變數在往上移到 /Views/Home/_ViewsStart.cshtml
或者再更往上 /Views/_ViewStart.cshtml
參考:https://dotblogs.com.tw/supershowwei/2020/04/06/090251
_Layout.cshtml 設定每個頁面獨立加 style & script
在 _Layout.cshtml
加上 RenderSectionAsync(Name, required: false)
,然後 /Views/Home/Index.cshtml
加上 @section Name { ... }
,這樣每個頁面都能添加自己的 <style></style>
和 <script></script>
很像寫 Vue SPA,每個 component 都有自己的 <template>
& <script>
& <style>
。
@* /Views/Shared/_Layout.cshtml *@
<!DOCTYPE html>
<html lang="en">
<head>
@await RenderSectionAsync("AdditionalCSS", required: false)
</head>
<body>
@RenderBody()
@await RenderSectionAsync("AdditionalScript", required: false)
</body>
</html>
@* /Views/Home/Index.cshtml *@
@{
ViewBag.Title = "首頁";
}
@section AdditionalCSS
{
<style>
body {
color: red;
}
</style>
}
@section AdditionalScript
{
<script>
console.log("Hello World ~");
</script>
}
各別頁面使用不同 Layout
當 URL: /Home/Index
會先看 /Views/_ViewStart.cshtml
設定的 Layout 是哪一個,當然也可以在 /Views/Home/Index.cshtml
最上方宣告要使用哪一個 Layout。
建立兩個 Layout 來做測試,一個 _Layout.cshtml
另一個 _LayoutTest.cshtml
,不同的地方在於 h1
的內容,接著在 /Views/Home/Index.cshtml
最上方宣告使用 Layout = "_LayoutTest";
就可以囉
@* /Views/Shared/_Layout.cshtml *@
<!DOCTYPE html>
<html lang="en">
<head>
@*
5 ways to render a partial view in asp.net core
https://nitishkaushik.com/how-to-render-a-partial-view-in-asp-net-core/
*@
<partial name="_Head" />
@await RenderSectionAsync("AdditionalCSS", required: false)
</head>
<body>
<h1>_Layout</h1>
@RenderBody()
@await RenderSectionAsync("AdditionalScript", required: false)
</body>
</html>
@* /Views/Shared/_LayoutTest.cshtml *@
<!DOCTYPE html>
<html lang="en">
<head>
@*
5 ways to render a partial view in asp.net core
https://nitishkaushik.com/how-to-render-a-partial-view-in-asp-net-core/
*@
<partial name="_Head" />
@await RenderSectionAsync("AdditionalCSS", required: false)
</head>
<body>
<h1>_Layout Test</h1>
@RenderBody()
@await RenderSectionAsync("AdditionalScript", required: false)
</body>
</html>
@* /Views/Home/Index.cshtml *@
@{
ViewBag.Title = "首頁";
Layout = "_LayoutTest";
}
各別資料夾下的頁面使用同個 Layout
/Views/_ViewStart.cshtml
是設定 /Views
底下所有頁面的 Layout,但是今天我想設定在 /Views/Home
底下頁面的 Layout 就需要在 /Views/Home
底下新增 _ViewStart.cshtml
。
讀取順序會是 /Views/_ViewStart.cshtml
> /Views/Home/_ViewStart.cshtml
防止 js/css/圖檔舊版 Cache 搗亂
在 <link rel="stylesheet" href="..." />
或 <Script src=".."></script>
加上 asp-append-version="true"
測試結果當內容有改變時會自動 random ?v=xxx
@* /Views/Shared/_Head.cshtml *@
<link rel="stylesheet" asp-append-version="true" href="~/css/chunk-vendors.min.css" />
<link rel="stylesheet" asp-append-version="true" href="~/css/all.min.css" />
@* ============================== *@
@* /Views/Shared/_Script.cshtml *@
<script src="~/js/chunk-vendors.js" asp-append-version="true"></script>
@if (ViewBag.CurrentEnvironment == "Production")
{
<script src="~/js/vue.prod.js" asp-append-version="true"></script>
}
else
{
<script src="~/js/vue.dev.js" asp-append-version="true"></script>
}
Vue Demo
接下來用 Vue
做一個在畫面顯示 Hello Vue ~
和一個按鈕點下去數字會一直增加。
啟動時可以切換 ProjectName-Dev
和 ProjectName-Prod
就會發現載入 Vue
的版本不一樣唷
@* /Views/Home/Index.cshtml *@
@{
ViewBag.Title = "首頁";
}
<div id="app">
<div class="container">
<h1>{{ message }}</h1>
<button type="button" class="btn btn-outline-primary" @@click="count++">{{ count }}</button>
</div>
</div>
@section AdditionalScript
{
<script>
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const message = "Hello Vue ~";
const count = ref(0);
onMounted(() => {
console.log(`count: ${count.value}`);
});
return {
message,
count
}
}
}).mount('#app');
</script>
}
Sweet Alert 2 Demo
# terminal
$ npm i -S sweetalert2@11.6.8
// bundleconfig.json
[
{
"outputFileName": "wwwroot/js/chunk-vendors.js",
"inputFiles": [
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
"node_modules/sweetalert2/dist/sweetalert2.all.min.js"
]
},
...
]
@* /Views/Home/Index.cshtml *@
@section AdditionalScript
{
<script>
Swal.fire({
title: 'Error!',
text: 'Do you want to continue',
icon: 'error',
confirmButtonText: 'Cool'
});
</script>
}