在以前的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系统。
更多内容烦请关注个人博客《高先生小屋》