在以前的4篇的內容裏,咱們較爲詳細的介紹了路由以及控制器還有視圖之間的關係。也就是說,系統如何從用戶的HTTP請求解析到控制器裏,而後在控制器裏處理數據,並返回給視圖,在視圖中顯示出來。這一篇我將爲你們介紹基礎的最後一部分,佈局頁和靜態資源引入。css
在控制器和視圖那一篇,咱們瞭解到_ViewStart
裏設置了一個Layout屬性的值,這個值正是用來設置佈局頁的。所謂的佈局頁,就是視圖的公用代碼。在實際開發中,佈局頁一般存放咱們爲整個系統定義的頁面框架,視圖裏寫每一個視圖的頁面。html
回顧一下,默認的_ViewStart
裏的內容是:jquery
@{ Layout = "_Layout"; }
默認的佈局頁指定的是名爲_Layout
的佈局頁,在本系列第三篇中,咱們得知這個視圖應當在Shared文件夾下,那咱們進去看一下這個視圖有什麼內容:web
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - MvcWeb</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-controller="Home" asp-action="Index">MvcWeb</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-controller="Home" asp-action="Index">Home</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="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"> © 2020 - MvcWeb - <a asp-area="" asp-controller="Home" asp-action="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>
這是默認的佈局頁內容,看着挺多的,可是除了一些html代碼,裏面還有一些關鍵的地方須要注意。json
RenderSection 分部渲染,在頁面中建立一個標記,表示這個頁面塊將在子視圖(或者是路由的實際渲染視圖)中添加內容。bootstrap
來,咱們看一下微軟官方給的註釋:c#
In layout pages, renders the content of the section named
name
.數組
意思就是在佈局頁中,渲染名稱爲name的分部內容。瀏覽器
新建立一個分佈頁,名稱爲_Layout1
:緩存
<html> <head> <title>Render 測試</title> </head> <body> @RenderSection("SectionDemo") </body> </html>
這個佈局頁裏什麼都沒有,只有一個RenderSection。如今咱們新建一個控制器:
using Microsoft.AspNetCore.Mvc; namespace MvcWeb.Controllers { public class RenderTestController : Controller { public IActionResult Index() { return View(); } } }
建立對應的視圖:
Views / RenderTest/Index.cshtml
先設置佈局頁爲_Layout1
:
@{ Layout = "_Layout1"; }
先試試啓動應用,訪問:
正常狀況下,你應該能看到這個頁面:
仔細看一下信息,意思是在 RenderTest/Index.cshtml 視圖中沒有找到 SectionDemo 的分部內容。
那麼,如何在視圖中設置分部內容呢?
@{ Layout = "_Layout1"; } @section SectionDemo{ <h1>你好</h1> }
使用 @section <Section 名稱> 後面跟一對大括號,在大括號中間的內容就是這個section(分部)的內容。
重啓應用,而後刷新頁面,你能看到這樣的頁面:
若是不作特殊要求的話,定義在佈局頁中的分部塊,視圖必須實現。固然,RenderSection還有一個參數,能夠用來設置分部不是必須的:
public HtmlString RenderSection(string name, bool required);
先看下微軟給的官方註釋:
In a Razor layout page, renders the portion of a content page that is not within a named section.
簡單講,若是在佈局頁中設置了@RenderBody,那麼在使用了這個佈局頁的視圖裏全部沒被分部塊包裹的代碼都會渲染到佈局頁中聲明瞭@RenderBody的地方。
修改_Layout1.cshtml
:
<html> <head> <title>Render 測試</title> </head> <body> <h1>RenderBody 測試 -以前</h1> @RenderBody() <h1>RenderBody 測試 -以後</h1> </body> </html>
修改RenderTest/Index.cshtml
:
@{ Layout = "_Layout1"; } RenderBody測試 <h1>我是視圖的內容!</h1>
重啓應用,刷新剛剛訪問的頁面:
能夠看出,RenderBody渲染的位置。
一般狀況下,靜態資源的引入與HTML引用js和css等資源是一致的,可是對於咱們在編寫系統時本身建立的腳本和樣式表,asp.net core提供了不一樣的處理方式。那就是服務器端壓縮功能。
asp.net core 3.0 的mvc 默認項目是不啓動這個功能的,須要咱們額外的開啓支持。
先引入 BuildBundleMinifier
cd MvcWeb # 切換目錄到MvcWeb項目下 dotnet add package BuildBundleMinifier
建立 bundleconfig.json
[ { "outputFileName": "wwwroot/css/site.min.css", "inputFiles": [ "wwwroot/css/site.css" ] }, { "outputFileName": "wwwroot/js/site.min.js", "inputFiles": [ "wwwroot/js/site.js" ], "minify": { "enabled": true, "renameLocals": true }, "sourceMap": false } ]
每一個節點容許設置項:
正常狀況下在佈局頁中,把壓縮後的文件路徑引入便可。不過在開發中,一般按照如下方式引用:
<environment exclude="Development"> <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" /> </environment> <environment include="Development"> <link rel="stylesheet" href="~/css/site.css" /> </environment>
注: asp-append-version 表示在引用路徑追加一個版本號,這是針對html靜態資源緩存的問題的一個解決方案,這一步是由程序決定的。
environment表示環境,如今你們知道這個寫法就行,在接下來的篇幅會講。
咱們知道到目前爲止,咱們的靜態資源都是在wwwroot目錄下。那麼咱們是否能夠修改或者添加別的目錄做爲靜態資源目錄呢?
在Startup.cs文件內的Configure方法下有這樣一行代碼:
app.UseStaticFiles();
這行代碼的意思就是啓用靜態文件,程序自動從 wwwroot尋找資源。那麼,咱們就能夠從這個方法入手,設置咱們本身的靜態資源:
public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, StaticFileOptions options);
咱們找到了這個方法的另外一個重載版本,裏面有一個參數類:
public class StaticFileOptions : SharedOptionsBase { public StaticFileOptions(); public StaticFileOptions(SharedOptions sharedOptions); public IContentTypeProvider ContentTypeProvider { get; set; } public string DefaultContentType { get; set; } public HttpsCompressionMode HttpsCompression { get; set; } public Action<StaticFileResponseContext> OnPrepareResponse { get; set; } public bool ServeUnknownFileTypes { get; set; } }
並無發現咱們想要的,先別慌,它還有個父類。咱們再去它的父類裏看看:
public abstract class SharedOptionsBase { protected SharedOptionsBase(SharedOptions sharedOptions); public IFileProvider FileProvider { get; set; } public PathString RequestPath { get; set; } protected SharedOptions SharedOptions { get; } }
這下就比較明瞭了,須要咱們提供一個文件提供器,那麼咱們來找一個合適的IFileProvider實現類吧:
public class PhysicalFileProvider : IFileProvider, IDisposable
這個類能夠知足咱們的要求,它位於命名空間:
namespace Microsoft.Extensions.FileProviders
那麼,添加一組咱們本身的配置吧:
using Microsoft.Extensions.FileProviders; public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 省略其餘代碼,僅添加如下代碼 app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),"OtherStatic")), }); }
在項目的根目錄建立名爲OtherStatic的文件夾,而後在裏面建立個文件夾,例如: files,並在這個文件夾裏隨便添加一個文件。
而後啓動應用訪問:
http://localhost:5006/files/<你添加的文件(包括後綴名)>
而後能在瀏覽器中看到這個文件被正確響應。
固然,這裏存在一個問題,若是在 OtherStatic中的文件在wwwroot也有相同目錄結構的文件存在,這樣訪問就會出現問題。這時候,能夠爲咱們新加的這個配置設置一個請求前綴:
app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),"OtherStatic")), RequestPath = "/other" });
重啓程序,而後訪問:
http://localhost:5006/other/files/<你添加的文件(包括後綴名)>
而後就能看到剛纔響應的文件,從新訪問以前的路徑,發現瀏覽器提示404。
在這一篇,咱們講解了佈局頁的內容,靜態資源的壓縮綁定以及添加一個新的靜態資源目錄。經過這幾篇內容,讓咱們對asp.net core mvc有了一個基本的認知。下一篇,咱們將從新建立一個項目,並結合以前的內容,以實戰爲背景,帶領你們完成一個功能完備的web系統。
更多內容煩請關注個人博客《高先生小屋》