1. 什么是Mvc
模型-视图-控制器 (MVC) 体系结构模式将应用程序分成 3 个主要组件组:视图模型、视图和控制器。 此模式有助于实现关注点分离。 使用此模式,用户请求被路由到控制器,后者负责使用模型来执行用户操作和/或检索查询结果。 控制器选择要显示给用户的视图,并为其提供所需的任何模型数据。
下图显示 3 个主要组件及其相互引用关系:
这种责任划分有助于根据复杂性缩放应用程序,因为这更易于编码、调试和测试包含单一作业的某个组成部分(模型、视图或控制器)。 但这会加大更新、测试和调试代码的难度,该代码在这 3 个领域的两个或多个领域间存在依赖关系。 例如,用户界面逻辑的变更频率往往高于业务逻辑。 如果将表示代码和业务逻辑组合在单个对象中,则每次更改用户界面时都必须修改包含业务逻辑的对象。 这常常会引发错误,并且需要在每次进行细微的用户界面更改后重新测试业务逻辑。
视图和控制器均依赖于模型。 但是,模型既不依赖于视图,也不依赖于控制器。 这是分离的一个关键优势。 这种分离允许模型独立于可视化展示进行构建和测试。
模型责任
MVC 应用程序的模型 (M) 表示应用程序和任何应由其执行的业务逻辑或操作的状态。 业务逻辑应与保持应用程序状态的任何实现逻辑一起封装在模型中。 强类型视图通常使用 ViewModel 类型,旨在包含要在该视图上显示的数据。 控制器从模型创建并填充 ViewModel 实例。
视图责任
视图 (V) 负责通过用户界面展示内容。 它们使用 Razor 视图引擎 在 HTML 标记中嵌入 .NET 代码。 视图中应该有最小逻辑,并且其中的任何逻辑都必须与展示内容相关。 如果发现需要在视图文件中执行大量逻辑以显示复杂模型中的数据,请考虑使用 View Component、ViewModel 或视图模板来简化视图。
控制器职责
控制器 (C) 是处理用户交互、使用模型并最终选择要呈现的视图的组件。 在 MVC 应用程序中,视图仅显示信息;控制器处理并响应用户输入和交互。 在 MVC 模式中,控制器是初始入口点,负责选择要使用的模型类型和要呈现的视图(因此得名 - 它控制应用如何响应给定请求)。
备注
控制器不应由于责任过多而变得过于复杂。 要阻止控制器逻辑变得过于复杂,请将业务逻辑推出控制器并推入域模型。
提示
如果发现控制器操作经常执行相同类型的操作,可将这些常见操作移入筛选器。
2. ASP.NET Core MVC
ASP.NET Core MVC 框架是轻量级、开源、高度可测试的演示框架,并针对 ASP.NET Core 进行了优化。它摒弃了传统的全家桶模式,采用了按需所取的方式给用户提供服务。
ASP.NET Core MVC 提供一种基于模式的方式,用于生成可彻底分开管理事务的动态网站。 它提供对标记的完全控制,支持 TDD 友好开发并使用最新的 Web 标准。
1. 与Framework 下的 Asp.Net Mvc 的区别
详细内容: ASP.NET MVC 和 ASP.NET Core 之间的体系结构差异 | Microsoft Docs
差异 | Frameowrk Mvc | Mvc Core |
体系结构
非跨平台
跨平台
启动方式
ASP.NET 应用托管在 IIS 中,它们依赖于 IIS 来实例化某些对象,并在请求到达时调用某些方法。
ASP.NET Core 应用是独立程序。 因此,它们通常包含一个 Program.cs 文件,该文件包含应用的入口点 .
托管差异
ASP.NET MVC 应用托管在 IIS 中,并可能依赖 IIS 配置来实现其行为。 这通常包括 IIS 模块。
使用了更轻量的kestrel 服务器,它可支持跨平台
静态文件
由 IIS 托管静态文件。支持将静态文件与应在服务器上保持私有的文件并排放置。(可使用内容分发网络CDN优化)
不能直接支持,必须配置静态文件中间件。(wwwroot为固定文件夹)
注入差异
需要借助第三方工具,如Autofac,Unity,Ninject...
内置于框架中,在应用启动时,将调用 ConfigureServices
,该调用负责注册 DI 容器(服务集合/服务提供商)可在应用中创建和注入的所有类型
模块和处理程序
HTTP 模块和 HTTP 处理程序是 ASP.NET 体系结构的必要部分。 处理请求时,每个请求都由多个 HTTP 模块(例如身份验证模块和会话模块)处理,然后由单个 HTTP 处理程序进行处理。 在处理程序处理请求后,请求通过 HTTP 模块传输回去。(全家桶)
ASP.NET Core 在每个应用的 Configure
方法中定义一个请求管道。 此请求管道定义了应用如何处理传入的请求,其中管道中的每个方法都调用下一个方法,直到最终方法终止(按需所用)
配置差异
配置使用应用文件夹中内置的 .NET 配置文件web.config,ConfigurationManager静态访问
配置本身是可配置的。可根据需要注入IConfiguration访问配置值
2. Mvc:约定大于配置
-
控制器类加Controller后缀,而且都放在Web项目下的Controllers文件夹中,控制器类继承Controller基类。
-
视图文件必须放在名称为Views/Pages 的文件夹下的名称为控制器名称的文件夹中。
-
_ViewStart.cshtml 执行任何Action(控制器中以IActionResult为返回类型的方法叫Action方法)之前,都会先执行它.
-
以下划线命名开头的视图一般作为布局/ViewCompenent 视图,放在shared文件夹下面
-
_ViewImport.cshtm 为全局视图文件共公命名空间的引用
3. 快速入门
-
创建项目
刚新建好的空项目:
-
选中Controllers 文件夹,右键-->新建-->类/接口
-
控制器代码
// Hello 表示控制器名称,HelloController 是控制器类名(C)
public class HelloController:Controller
{
// 创建视图文件的方法(V)
public IActionResult Index()
{
// 业务逻辑,模型操作(M)
List<StudentViewModel> list = new List<StudentViewModel>()
{
new(1,"张三"), // C#9.0 以上创建对象语法
new(2,"李四"),
new (3,"王五")
};
return View(list);// 将模型数据传递给视图
}
}
public record StudentViewModel(int Id,string Name);
-
在Views/ 目录下创建Hello目录,在Hello目录下创建Index.cshtml文件。
-
编写任意html代码
@* 接收视图模型传递过来的数据 *@
@model List<WebApplication2.Controllers.StudentViewModel>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Mvc 快速入门</title>
</head>
<body>
<div>
<h1>大家好,欢迎来到任我行码农场,Asp.net Mvc</h1>
</div>
</body>
</html>
3. Mvc 项目结构
-
Dependencies:项目所依赖的组件
-
launchSettings.json : 项目发布设置文件
{
"iisSettings": {// iis 设置
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:21843",
"sslPort": 44331
}
},
"profiles": {
"WebApplication2": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,// 使用浏览器
"applicationUrl": "http://localhost:5096",// 项目运行地址
"environmentVariables": { // 当前环境
"ASPNETCORE_ENVIRONMENT": "Development" // 表示当前环境为Development
}
},
"IIS Express": { // 内置IIS 的设置
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
-
Controllers: 存放所有的控制器
-
Models: 存放所有的ViewModel 文件
-
Views: 存放所有的视图文件
-
Views/Shared : 存放公共的视图文件
-
Views/Shared/_Layout.cshtml : 公共布局文件
-
Views/Shared/Error.cshtml: 错误提示视图
-
Views/_ViewImports.cshtml: 公共导入命名空间,引用公共的标签助手
@using WebApplication2
@using WebApplication2.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewStart.cshtml: 视图起始文件,所有视图在加载时,都会先加载此视图文件
wwwroot: 存放所有的静态资源文件(css/js/html)
wwwroot/favicon.ico : 应用程序的图标
appsetting.json: 当前应用程序的配置文件
appsetting.Development.json: 当前环境的配置文件,如果在此文件中未找到想要的配置,则会去appsetting.json 文件中去寻找。
Program:程序的主入口,用于初始化系统的相关配置,注册服务,配置中间件与注册管道。
4. 控制器动作
控制器动作(具体的action)返回的结果叫做控制器动作结果,动作结果是控制器返回给浏览器请求的内容。ASP.NET Core MVC 框架支持几十种标准类型的动作结果,以下是常见的类型
动作名称 简要概述
ViewResult 返回视图
RedirectToActionResult 重定向到某个Action方法
JsonResult Json结果,可以用于Ajax应用程序
ContentResult 文本结果
RedirectResult 重定向到一个新的URL
FileResult 返回一个文件,一般用于下载
它们 都实现了IActionResult 接口。
public ViewResult Index()
{
List<StudentViewModel> list = new List<StudentViewModel>()
{
new(1,"张三"),
new(2,"李四"),
new (3,"王五")
};
return View(list);
}
public JsonResult Index2()
{
List<StudentViewModel> list = new List<StudentViewModel>()
{
new(1,"张三"),
new(2,"李四"),
new (3,"王五")
};
return Json(list);
}
public ContentResult Index3()
{
return Content("hello,任我行码农场");
}
public RedirectToActionResult Index4()
{
return RedirectToAction("Index2", "Hello");
}
public FileResult Download()
{
using MemoryStream ms = new MemoryStream();
var buffer = Encoding.UTF8.GetBytes("文件下载");
ms.Write(buffer);
return File(ms.ToArray(), "application/octet-stream", "测试文件.txt");
}
Action方法与普通方法的区别
Action方法是由Mvc 框架管理,Mvc 框架可以对Action方法进行处理与渲染(例如渲染视图,拦截请求等等),而普通则不受mvc 控制。
举个例子,ContentResult 通常的作用也是直接返回一个字符串,当我们执行Content("hello,任我行码农场")
时,我们只是告诉Mvc框架,我们需要返回 “hello,任我行码农场”
,而并非立即返回,Mvc 框架在此之后可能还会做很多的处理,或许在中间的某个环节,有可能请求被拦截,导致我们可能得到不同的结果(日后要讲的AOPA思想)。而return "hello,任我行码农场"
则是立即返回。
5. Razor视图
注释
@* *@
输出纯文本:
@:这里是妹子可以看的内容
编写C#代码
<html>
<head>
<title>Mvc 快速入门</title>
</head>
<body>
<div>
<h1>大家好,欢迎来到任我行码农场,Asp.net Mvc</h1>
@{
int a = 1;
int b = 2;
Console.WriteLine(a+b);
}
</div>
</body>
</html>
if else
<html>
<head>
<title>Mvc 快速入门</title>
</head>
<body>
<div>
<h1>大家好,欢迎来到任我行码农场,Asp.net Mvc</h1>
@if (true)
{
<h1>hello</h1>
}
else
{
<p>world</p>
}
</div>
</body>
</html>
视图传值
1. TempData
public IActionResult Index()
{
TempData["username"] = "任我行";
return View();
}
<body>
<div>
<h1>我的名称:@TempData["username"]</h1>
</div>
</body>
TempData 保存在Session中,Controller每次执行请求的时候,会从Session中先获取 TempData,而后清除Session,获取完TempData数据,虽然保存在内部字典对象中,但是其集合中的每个条目访问一次后就从字典表中删 除。具体代码层面,TempData获取过程是通过SessionStateTempDataProvider.LoadTempData方法从 ControllerContext的Session中读取数据,而后清除Session,故TempData只能跨Controller传递一次。
2.ViewBag 与 ViewData
ViewData:
ViewData 只在当前 Action 中有效,生命周期和 View 相同;
public IActionResult Index()
{
ViewData["username"] = "任我行";
return View();
}
<body>
<div>
<h1>我的名称:@ViewData["username"]</h1>
</div>
</body>
ViewBag
ViewBag其实本质就是ViewData,只是多了层Dynamic控制。所以,使用何种方式完全取决于你的个人爱好。
public IActionResult Index()
{
ViewBag.UserName = "任我行";
return View();
}
<body>
<div>
<h1>我的名称:@ViewBag.UserName</h1>
</div>
</body>
两者区别如下:
ViewData | ViewBag |
它是key/value字典集合
它是dynamic类型对象
从asp.net mvc1就有了
从asp.netmvc3才有
基于asp.netframework 3.5
基于asp.net framework4.0
viewdata比viewbag快
viewbag比viewdata慢
页面查询数据时需要转换合适的类型
在页面查询数据时不需要转换合适的类型
有一些类型转换代码
可读性较好
总结
1、ViewData和TempData是字典类型,赋值方式用字典方式,ViewData["myName"]
2、ViewBag是动态类型,使用时直接添加属性赋值即可 ViewBag.myName
3、ViewBag和ViewData只在当前Action中有效,等同于View
4、TempData可以通过转向继续使用(Server.Tranfer()),因为它的值保存在Session中。但TempData只能经过一次传递,之后会被系统自动清除(Framework)
5、ViewData和ViewBag中的值可以互相访问,因为ViewBag的实现中包含了ViewData
配套视频链接:Asp.Net Mvc Core 6.0 详细教程 - 网易云课堂 (163.com)
海阔平鱼跃,天高任我行,给我一片蓝天,让我自由翱翔。