第一单元 Mvc概述

发布时间 2023-12-05 21:53:52作者: 誉尚学教育

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 MvcMvc 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:约定大于配置

  1. 控制器类加Controller后缀,而且都放在Web项目下的Controllers文件夹中,控制器类继承Controller基类。

  2. 视图文件必须放在名称为Views/Pages 的文件夹下的名称为控制器名称的文件夹中。

  3. _ViewStart.cshtml 执行任何Action(控制器中以IActionResult为返回类型的方法叫Action方法)之前,都会先执行它.

  4. 以下划线命名开头的视图一般作为布局/ViewCompenent 视图,放在shared文件夹下面

  5. _ViewImport.cshtm 为全局视图文件共公命名空间的引用

3. 快速入门

  1. 创建项目

 

刚新建好的空项目:

 

  1. 选中Controllers 文件夹,右键-->新建-->类/接口

     

  2. 控制器代码

// 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);

 

  1. 在Views/ 目录下创建Hello目录,在Hello目录下创建Index.cshtml文件。

  2. 编写任意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>

 

两者区别如下:

ViewDataViewBag
它是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

 
配套视频链接:什么是Mvc (cctalk.com)