• ASP.NET Core 中的 MVC架构


    MVC 架构

    MVC架构把 App 按照逻辑分成三层:

    • Controllers,接收 http request,配合 model,通过http response 返回 view,尽量不做别的事
    • Models, 负责业务逻辑,App 的状态,以及数据处理
    • Views,呈现 UI,如果UI 较复杂,应该使用View 组件, ViewModel, 或者 view 模板

    Controller

    ASP.NET Core MVC 中的所有 Controller 都继承于 Controller 基类,而 ASP.NET Core WEB API 中的 Controller 都继承于 ControllerBase 基类,是因为Controller 基类支持 View。
    Controller 可以返回三种类型的结果:

    • HTTP 状态码 或者 Redirect 结果
    • View 或者 格式化的结果(比如:Json(customer))
    • 与 Client 请求协商的结果

    View

    View 是使用 Razor 引擎标记的 HTML 模板页面。
    Razor 引擎标记在服务端生成 HTML。
    HMTL 中的 Razor 标记以 @ 开头,中间是{ … }。比如:

    @{
        ViewData["Title"] = "About";
    }
    
    • 1
    • 2
    • 3

    具体语法参考:
    https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-8.0#razor-syntax
    ASP.NET Core MVC 中的一个 View 是一个 .cshtml 代码文件。
    在这里插入图片描述
    一般一个 Controller 对应一个 View 文件夹,一个Action 可能对应一个 View。
    View 的文件夹结构一般是:Views/[ControllerName] 。
    多个 Controller 共享的 View 放在 Views/Shared 中。
    View 的名称一般与 Action 的名称相同。
    如果Action返回的 View 不指定具体View名称,则返回与 Action 方法相同的 View。
    此时 ASP.NET Core 会从Views/[ControllerName]和Views/Shared 中查找同名 View。

    return View();
    
    • 1

    Action 也可以显示指定 View 名称:

    return View("Orders");
    
    • 1

    Action 显示指定 View 名称的时候,使用相对路径:

    return View("../Manage/Index");
    
    • 1

    或者:

    return View("./About");
    
    • 1

    Action 也可以不指定名称,但指定 Model:

    return View(Orders);
    
    • 1

    Action 也可以同时指定名称和 Model:

    return View("Orders", Orders);
    
    • 1

    向 View 传递数据可以使用强类型的 ViewModel 或者弱类型的 ViewData

    ViewModel

    也可以向 View 传一个 ViewModel,ViewModel是用于 View 的强类型 Model。
    强类型意味着每个View 中的变量都在Model有对应的定义,使用 @model 指令:

    @model WebApplication1.ViewModels.Address
    
    <h2>Contacth2>
    <address>
        @Model.Street<br>
        @Model.City, @Model.State @Model.PostalCode<br>
        <abbr title="Phone">P:abbr> 425.555.0100
    address>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后通过 return View(ViewModel) 传递给View:

    public IActionResult Contact()
    {
        ViewData["Message"] = "Your contact page.";
    
        var viewModel = new Address()
        {
            Name = "Microsoft",
            Street = "One Microsoft Way",
            City = "Redmond",
            State = "WA",
            PostalCode = "98052-6399"
        };
    
        return View(viewModel);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ViewModel 类一般就是一个 POCO 类,即只有属性,没有方法的数据类。

    ViewData

    ViewData 是一个kv 结构的字典结构数据。
    弱类型意味着即使 View 中找不到数据,也不会报错。
    比如在 View 中使用的ViewData[“Greeting”]和ViewData[“Address”]:

    @{
        // Since Address isn't a string, it requires a cast.
        var address = ViewData["Address"] as Address;
    }
    
    @ViewData["Greeting"] World!
    
    <address>
        @address.Name<br>
        @address.Street<br>
        @address.City, @address.State @address.PostalCode
    address>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    通过 Action 中定义后通过return View() 传给 View:

    public IActionResult SomeAction()
    {
        ViewData["Greeting"] = "Hello";
        ViewData["Address"]  = new Address()
        {
            Name = "Steve",
            Street = "123 Main St",
            City = "Hudson",
            State = "OH",
            PostalCode = "44236"
        };
    
        return View();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    也可以通过ViewData 属性定义:

    public class HomeController : Controller
    {
        [ViewData]
        public string Title { get; set; }
    
        public IActionResult About()
        {
            Title = "About Us";
            ViewData["Message"] = "Your application description page.";
    
            return View();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Partial View

    当需要拆分大型 View 或者复用小型View时,可以使用 Partial View功能。
    Partial View 中没有 @page 指令。
    Partial View 不运行 _ViewStart.cshtml。
    Partial View 的名称通常以下划线 _ 开头。
    Action 返回 Partial View:

    public IActionResult OnGetPartial() =>
        Partial("_AuthorPartialRP");
    
    • 1
    • 2

    在 View 中通过 Tag Helper 使用 Partial View:

    <partial name="_PartialName" />
    
    • 1
    Partial View 的搜索路径

    MVC 中:

    1. /Areas//Views/
    2. /Areas//Views/Shared
    3. /Views/Shared
    4. /Pages/Shared

    Razer Page 中:

    1. 当前页面文件夹
    2. 当前页面的上一级文件夹
    3. /Shared
    4. /Pages/Shared
    5. /Views/Shared
    异步 HTML Helper

    使用HTML Helper时,一般使用 PartialAsync。
    PartialAsync 返回 Task 类型的 IHtmlContent。

    @await Html.PartialAsync("_PartialName")
    
    • 1

    Layout

    Web App 一般都有布局,类似这样:
    在这里插入图片描述
    默认的布局文件名放在 Views/Shared/_Layout.cshtml 。
    Layout 中一般会调用:

    @RenderBody()
    
    • 1

    Layout 中可以引用多个部分,每个部分通过RenderSection替换:

    <script type="text/javascript" src="~/scripts/global.js">script>
    
    @RenderSection("Scripts", required: false)
    
    • 1
    • 2
    • 3

    路由 Routing

    路由的作用是把客户端的 http 请求 url 映射到Controllers的具体类的具体 Action 上。
    路由语法可以参考 https://blog.csdn.net/cuit/article/details/132587534
    比如:

    初始时时基于约定的路由:

    routes.MapRoute(name: "Default", template: "{controller=Home}/{action=Index}/{id?}");
    
    • 1

    Controller中基于属性的路由:

    [Route("api/[controller]")]
    public class ProductsController : Controller
    {
        [HttpGet("{id}")]
        public IActionResult GetProduct(int id)
        {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Model 绑定

    Model 绑定功能把客户端的请求数据(表彰数据,路由数据,请求字符串,HTTP header)转换成 controller可以接收的对象。这样,controller 就不用分析请求数据,直接把请求数据作为 Action 的入参。

    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) { ... }
    
    • 1

    Model 验证

    使用Model 绑定功能后,可以在客户端发送请求之前就验证请求数据,以及在 Action 处理之前验证数据。

    using System.ComponentModel.DataAnnotations;
    public class LoginViewModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; }
    
        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    
        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Action的代码:

    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
          // work with the model
        }
        // At this point, something failed, redisplay form
        return View(model);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    .NET 会同时在客户端和服务端进行 Model 验证。

    依赖注入

    可以在 Controller 的构造函数中注入依赖类,也可以在 View 中使用 @inject 指令注入:

    @inject SomeService ServiceName
    
    DOCTYPE html>
    <html lang="en">
    <head>
        <title>@ServiceName.GetTitletitle>
    head>
    <body>
        <h1>@ServiceName.GetTitleh1>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    筛选器 Filters

    Filters 用于预处理或者后处理 pipeline 中的请求,比如异常处理,缓存,Authorization,日志。
    比如:
    在这里插入图片描述

    Areas

    Areas 用于分组功能。
    MVC 架构中,Model, Controller, 和 View 代码放在不同的物理文件夹中。
    而在大型 App 中,还需要把每个Controller/Model/View模块按功能放在不同的子分组中。

    强类型的 View

    Controllers 可以向 View 返回一个强类型 Model 的 View。
    比如这个类型为IEnumerable的 View。

    @model IEnumerable<Product>
    <ul>
        @foreach (Product p in Model)
        {
            <li>@p.Name</li>
        }
    </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Tag Helpers

    Tag Helpers 用于 server 端生成 HTML。
    Tag Helpers 可以自定义 HTML元素或者修改现有 HTML 元素。
    Tag Helpers 绑定到 HTML元素的属性上。
    Tag Helpers 有原生支持和第三方开发的。
    比如:LinkTagHelper 可以用于创建指向AccountsController.Login 的链接。

    <p>
        Thank you for confirming your email.
        Please <a asp-controller="Account" asp-action="Login">Click here to Log ina>.
    p>
    
    • 1
    • 2
    • 3
    • 4

    比如:EnvironmentTagHelper 可以用于根据环境使用不同的 HTML:

    <environment names="Development">
        <script src="~/lib/jquery/dist/jquery.js">script>
    environment>
    <environment names="Staging,Production">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.js"
                asp-fallback-test="window.jQuery">
        script>
    environment>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    内置的Tag Helpers

    • asp-controller 和asp-action,生成 URL,比如:
    <a asp-controller="Speaker"
       asp-action="Evaluations">Speaker Evaluationsa>
    
    • 1
    • 2

    生成:

    <a href="/Speaker/Evaluations">Speaker Evaluationsa>
    
    • 1
    • asp-route,asp-all-route-data,asp-route-{value},asp-area,匹配路由
    • asp-fragment,生成 html 锚点
    • asp-protocol,指定 http 协议,比如 https
    • asp-host,指定 url 的主机名
    • asp-page,生成 hrel 的超链接
    • cache,distributed-cache,缓存数据
    • environment,根据环境使用不同的 HTML
    • form,生成表单
      • formaction,提前表单
      • input,
      • label
      • select
      • textarea
      • asp-validation-for
      • asp-validation-summary
    • img,加强img标签。
    • Link 类
      • href
      • asp-fallback-href
    • partial,partial view
    • script
  • 相关阅读:
    力扣(2024.06.12)
    forest框架单个和批量添加头部信息
    阿里云SLB之:基于URL调度场景的SLB七层负载均衡配置(十三)
    IGS文件格式说明与下载方式- Renix atx ANTEX: The Antenna Exchange Format
    图像和图像处理
    mysql之存储过程
    STM32 使用内部晶振导致 Can 通讯异常
    亚马逊频繁扫号下的跨境电商,跨境电商卖家应该何去何从?
    GoWeb -- gin框架的入门和使用
    tictoc例子理解10-13
  • 原文地址:https://blog.csdn.net/cuit/article/details/132644726