0. 前言

在之前的4篇的内容里,我们较为详细的介绍了路由以及控制器还有视图之间的关系。也就是说,系统如何从用户的HTTP请求解析到控制器里,然后在控制器里处理数据,并返回给视图,在视图中显示出来。这一篇我将为大家介绍基础的最后一部分,布局页和静态资源引入。

1. 布局页

在控制器和视图那一篇,我们了解到_ViewStart 里设置了一个Layout属性的值,这个值正是用来设置布局页的。所谓的布局页,就是视图的公用代码。在实际开发中,布局页通常存放我们为整个系统定义的页面框架,视图里写每个视图的页面。

回顾一下,默认的_ViewStart里的内容是:

@{
Layout = "_Layout";
}

默认的布局页指定的是名为_Layout的布局页,在本系列第三篇中,我们得知这个视图应当在Shared文件夹下,那我们进去看一下这个视图有什么内容:

<!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">
&copy; 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代码,里面还有一些关键的地方需要注意。

1.1 RenderSection

RenderSection 分部渲染,在页面中创建一个标记,表示这个页面块将在子视图(或者是路由的实际渲染视图)中添加内容。

来,我们看一下微软官方给的注释:

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";
}

先试试启动应用,访问:

http://localhost:5006/RenderTest/Index

正常情况下,你应该能看到这个页面:

仔细看一下信息,意思是在 RenderTest/Index.cshtml 视图中没有找到 SectionDemo 的分部内容。

那么,如何在视图中设置分部内容呢?

@{
Layout = "_Layout1";
}
@section SectionDemo{
<h1>你好</h1> }

使用 @section <Section 名称> 后面跟一对大括号,在大括号中间的内容就是这个section(分部)的内容。

重启应用,然后刷新页面,你能看到这样的页面:

如果不做特殊要求的话,定义在布局页中的分部块,视图必须实现。当然,RenderSection还有一个参数,可以用来设置分部不是必须的:

public HtmlString RenderSection(string name, bool required);

1.2 RenderBody

先看下微软给的官方注释:

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渲染的位置。

2. 静态资源引入

通常情况下,静态资源的引入与HTML引用js和css等资源是一致的,但是对于我们在编写系统时自己创建的脚本和样式表,asp.net core提供了不同的处理方式。那就是服务器端压缩功能。

asp.net core 3.0 的mvc 默认项目是不启动这个功能的,需要我们额外的开启支持。

2.1 开启支持

先引入 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
}
]

每个节点允许设置项:

  • outputFileName 生成的捆绑压缩文件,通常路径携带wwwroot
  • inputFiles 数组,包含要压缩到此次输出文件的文件路径,会按照添加的顺序依次加入
  • minify 输出类型的缩小选项,可选。 默认是 enabled: true
  • sourceMap 表示是否为捆绑的文件生成源映射的标记
  • sourceMapRootPath 源映射文件的路径

2.2 使用

正常情况下在布局页中,把压缩后的文件路径引入即可。不过在开发中,通常按照以下方式引用:

<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表示环境,现在大家知道这个写法就行,在接下来的篇幅会讲。

3. 静态资源目录

我们知道到目前为止,我们的静态资源都是在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。

4. 总结

在这一篇,我们讲解了布局页的内容,静态资源的压缩绑定以及添加一个新的静态资源目录。通过这几篇内容,让我们对asp.net core mvc有了一个基本的认知。下一篇,我们将重新创建一个项目,并结合之前的内容,以实战为背景,带领大家完成一个功能完备的web系统。

更多内容烦请关注我的博客《高先生小屋》

【asp.net core 系列】5 布局页和静态资源的更多相关文章

  1. asp.net core系列 44 Web应用 布局

    一.概述 MVC的视图与Razor页面经常共享视觉和程序元素,通过使用布局来完成,布局还可减少重复代码.本章演示了以下内容的操作方法:(1)使用通用布局,(2)自定义布局,(3) 共享指令,(4)在呈 ...

  2. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

  3. asp.net core系列 40 Web 应用MVC 介绍与详细示例

    一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...

  4. asp.net core系列 39 Web 应用Razor 介绍与详细示例

    一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...

  5. asp.net core系列 39 Razor 介绍与详细示例

    原文:asp.net core系列 39 Razor 介绍与详细示例 一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor ...

  6. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

  7. 【asp.net core 系列】3 视图以及视图与控制器

    0.前言 在之前的几篇中,我们大概介绍了如何创建一个asp.net core mvc项目以及http请求如何被路由转交给对应的执行单元.这一篇我们将介绍一下控制器与视图直接的关系. 1. 视图 这里的 ...

  8. asp.net core系列 38 WebAPI 返回类型与响应格式--必备

    一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...

  9. asp.net core 系列 14 错误处理

    一.概述 本文介绍处理 ASP.NET Core 应用中常见错误的一些方法.主要是关于:开发环境异常页:非开发环境配置自定义异常处理页:配置状态代码页(没有正文响应,http状态400~599的). ...

随机推荐

  1. wpf winform 截图

    wpf 通过下面的截图,标题可能会丢失. public void CreateBitmapFromVisual(Window win, string fileName)        {        ...

  2. 手把手教你用Python网络爬虫获取网易云音乐歌曲

    前天给大家分享了用Python网络爬虫爬取了网易云歌词,在文尾说要爬取网易云歌曲,今天小编带大家一起来利用Python爬取网易云音乐,分分钟将网站上的音乐down到本地. 跟着小编运行过代码的筒子们将 ...

  3. 搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式

    搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : model - view - viewmodel的缩写,说都能直接说出来 model:模型,view:视图,view-Model:视 ...

  4. 5.5 Go defer

    5.5 Go defer 程序开发中经常要创建资源(数据库初始化连接,文件句柄,锁等),在程序执行完毕都必须得释放资源,Go提供了defer(延时机制)更方便.更及时的释放资源. 1.内置关键字def ...

  5. 01 基础版web框架

    01 基础版web框架 服务器server端python程序(基础版): import socket server=socket.socket() server.bind(("127.0.0 ...

  6. Redis 消息中间件 ServiceStack.Redis 轻量级

    问题: 公司开了个新项目,算上我一共3个人.车间里机台通过流水线连通联动的玩意.一个管理控制系统连接各个机台和硬件.专机类型就有5种,个数差不多20个左右. 软件规划的时候采用总分的结构,管理控制系统 ...

  7. poj3613 求经过n条边的最短路 ----矩阵玩出新高度 。

    For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race usin ...

  8. 3、JSP中的Cookie 用于存储 web 页面的用户信息。

    cookie 在平时生活中的运用 存储用户在网页上的登陆信息,包括账号和密码. 有的网站,登陆的时候,会出现一个选项,问你是否要一周内或者一个月内保持登陆状态.如果你选了,那么一周之内,都不需要再输入 ...

  9. [推荐]大量 Blazor 学习资源(一)

    前言 / Introduction Blazor 是什么? Blazor 允许您使用 C# 而不是 JavaScript 构建交互式 Web UI. Blazor 应用由使用 C#.HTML 和 CS ...

  10. vue项目中关闭eslint的方法

    非常简单的操作方法!不用再去为了烦人的代码标准报错而苦恼了! 方法一:在项目根目录下增加 vue.config.js 文件 添加以下代码: module.exports = { lintOnSave: ...