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


    0.前言

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

    1. 视图

    这里的视图不是数据库里的视图,是一种展示技术。在asp.net core mvc项目中视图是指以cshtml做扩展名的文件,通常在Views文件夹。

    那么现在我们进到之前创建的测试项目 MvcWeb的Views目录下,如果小伙伴们没有做修改的话,能看到如下的目录结构:

    ├── Home
    │   ├── Index.cshtml
    │   └── Privacy.cshtml
    ├── Shared
    │   ├── Error.cshtml
    │   ├── _Layout.cshtml
    │   └── _ValidationScriptsPartial.cshtml
    ├── _ViewImports.cshtml
    └── _ViewStart.cshtml
    

    在Views根目录下,有两个文件分别是:_ViewImports.cshtml _ViewStart.cshtml 两个文件(注意,有个前置下划线)。

    1.1 在视图中引用命名空间

    我们知道,在cshtml文件中,虽然极大的减少了服务器代码,但是有时候无法避免的使用一些C#代码。那么就会产生一个问题,很多类都有自己的命名空间,如果我们在某个或某几个或某些视图中需要访问这些类和方法,那么一个视图一个视图的写引用有点不太现实,因为这太繁琐了。

    所以asp.net core mvc 设置了在名为_ViewImports.cshtml的文件中添加引用,则在Views下所有视图中都生效。那么,先来看看这个文件里有啥吧:

    @using MvcWeb
    @using MvcWeb.Models
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    

    可以看到,这里引用了项目的命名空间和项目下Modes命名空间的所有内容。因为我们之前创建的测试项目名称就是 MvcWeb。

    最后一行是一个 cshtml标记引用,第一个星号表示当前项目的所有TagHelper实现都引用,后面的表示引入aps.net core mvc内置的TagHelper。

    关于 TagHelper,这篇就先不介绍了。

    1.2 ViewsStart

    _ViewStart.cshtml 作用从名字中可见一二,这个文件用来配置一些在视图刚开始加载时的一些配置内容。先看一下,默认的里面是什么吧:

    @{
        Layout = "_Layout";
    }
    

    先做个介绍,@符号后面用一对大括号包裹,里面是C# 代码。也就是说 Layout = "_Layout",这行的意思是给某个名为Layout的属性设置值为_Layout

    那么,Layout的属性是哪里的呢?

    对于asp.net core mvc而言,一个视图也是一个类只不过这个类是动态生成的,不是一个由程序员编写出来的类,但是这个类继承自:

    namespace Microsoft.AspNetCore.Mvc.Razor
    {
        public abstract class RazorPageBase : IRazorPage
        {
        }
    }
    

    Layout正好是这个类的一个属性,表示视图是否使用了某个布局页。所以上面的代码表示,Views里的新建视图,默认是使用名为_Layout的视图作为布局页。

    当然,这个页面不只有这个作用,小伙伴们可以自己尝试下哦。

    1.3 视图检索

    在上一节中,我们指定了一个布局页的名称。布局页也是视图中的一种,但我们也只指定了名称,但没有指定路径。asp.net core是如何发现这个名称的视图呢?

    asp.net core 会按照以下顺序查找对应的视图文件:

    • Views/[ControllerName]/[ViewName].cshtml
    • Views/Shared/[ViewName].cshtml

    所以,_Layout也会按照这个顺序查找,为了避免不必要的混淆,我们只在Shared目录下写了_Layout.cshtml。这也是通常的做法,该文件表示一个全局的布局页。

    2. 控制器与视图的关系

    在上一篇《【asp.net core 系列】2 控制器与路由的恩怨情仇》中,我们介绍了三种创建控制器的方法,并且最后推荐使用名字以Controller结尾并继承Controller类的写法。我将在这里为大家再次讲解为什么推荐这样写:

    • 以Controller结尾,可以很明确的告诉其他人或者未来的自己这是一个控制器,不是别的类
    • 继承Controller,是因为Controller类为我们提供了控制器用到的属性和方法

    嗯,暂时就这两点。别看少,但是这很重要。

    2.1 使用视图

    在之前介绍的时候,有提到过当我们访问一个URL的时候,路由会自动为我们寻找到对应的可执行代码单元。但是,没有进一步内容的介绍。当我们寻找到对应的可执行代码单元也就是Action之后,Action进行一系列的处理,会对这个请求做出响应。有一种响应就是返回一个展示页面,也就是View。

    那么,如何返回一个View呢?

    创建一个控制器,名为ViewDemoController,并添加一个方法Index,返回类型为IActionResult

    using Microsoft.AspNetCore.Mvc;
    
    namespace MvcWeb.Controllers
    {
        public class ViewDemoController:Controller
        {
            public IActionResult Index()
            {
                return View();
            }
        }
    }
    

    其中 View() 表示返回一个View,这View的名称是 Index,在ViewDemo控制器下。所以,它的路径应该是:

    Views/ViewDemo/Index.cshtml
    

    在对应目录创建该文件,然后在文件里随便写一些内容,之后启动项目(项目的端口在第一部分就已经修改过了):

    http://localhost:5006 
    

    然后访问:

    http://localhost:5006/ViewDemo/
    

    image-20200601225734470

    应该是类似的页面。

    IActionResult 是一个接口,表示是一个Action的处理结果,在这里可以理解为固定写法。

    2.2 指定视图

    在控制器里,View 方法表示使用一个视图进行渲染,默认是使用方法同名的视图。当然,既然是默认的,那就一定有不默认的时候。对的,View方法提供了几个重载版本,这些重载版本里有一个名字为viewName的参数,这个参数就是用来指定视图名称的。

    那么,我们可以指定哪些视图名称:

    • 同一个控制器文件夹下的其他视图
    • Shared 文件夹下的视图

    这两种都是不用携带路径的视图名,可以省略文件扩展名(cshtml)。

    当然,还可以指定其他路径下的视图文件,如:

    • Views/Home/About.cshtml 表示从根目录下查找到这个视图,这种写法必须指定扩展名
    • ../Manage/Index 表示在Manage控制器目录下的Index

    2.3 给视图传递数据

    之前介绍了如何使用视图、如何指定视图名称,但是还缺最关键的一步,那就是如何给视图传递数据。

    通常情况下,Action方法中给视图传递数据,只有这三种是推荐的:

    • 使用ViewData
    • 使用ViewDataAttribute
    • 使用ViewBag
    • 使用ViewModel

    Controller类有一个属性是 ViewData,它的声明如下:

    public ViewDataDictionary ViewData { get; set; }
    

    可以看到这是一个字典型的属性,所以给它赋值是这样使用的:

    public IActionResult Index()
    {
        ViewData["Title"] = "ViewDemo";
        return View();
    }
    

    ViewBag也是 Controller类的一个属性,它的声明如下:

    public dynamic ViewBag { get; }
    

    可以看到这是一个动态类,实际上ViewBag里的数据与ViewData是互通的,换句话说就是ViewBag是对ViewData的一次封装,两者并没有实际上的区别。赋值使用:

    public IActionResult Index()
    {
        ViewBag.Name = "小李";
        return View();
    }
    

    而ViewDataAttribute则与上两个,不太一样,这个属性标注给控制器的属性上,asp.net core mvc就会把这个属性的值填充给ViewData,键值就是属性名:

    [ViewData]
    public string AttributeTest{get;set;}
    

    ViewData["AttributeTest"]效果一致。

    在View方法的一些重载版本里,需要一个名为 model的参数,类型是object。这个参数就是一个ViewModel。使用:

    在MvcWeb/Models 下添加一个类:

    namespace MvcWeb.Models
    {
        public class ViewModelTestModel
        {
            public string Name{get;set;}
            public int Age{get;set;}
        }
    }
    

    回到刚刚的Index方法里,创建一个ViewModelTestModel实例,并传给View方法:

    public IActionResult Index()
    {
        ViewData["Title"] = "ViewDemo";
        ViewBag.Name = "小李";
        var model = new ViewModelTestModel
        {
            Name = "测试实例",
            Age = 1
        };
        return View(model);
    }
    

    2.4 在视图中使用

    在上一小节中,我们分别使用ViewData和ViewBag以及ViewModel给视图传递了三个数据,那么如何在视图中获取这三个数据呢?

    <h2>@ViewData["Title"]</h2>
    <!--实际会显示 <h2>ViewDemo</h2>-->
    

    与字典一样,@起头,表示后面跟着一个属性或者一段C#表达式,并将表达式的结果输出到页面上。

    ViewBag的访问与ViewData类似,只不过ViewBag是动态对象,可以认为它的类型并没有发生改变,继续按照之前的类型进行使用:

    <h4>@ViewBag.Name</h4>
    

    对于ViewModel的使用,View内置了一个dynamic的Model属性,在不做特殊处理的情况下,我们在页面上使用@Model 会得到一个dynamic对象(如果传了ViewModel的话)。虽然也能用,但是这不太友好。

    这时候,就需要我们在视图的开头处,添加:

    @model ViewModelTestModel
    

    这时候,再使用@Model的时候,就会自动解析成ViewModelTestModel了。

    整体Index.cshtml内容如下:

    @model ViewModelTestModel
    Hello  World!
    <h2>@ViewData["Title"]</h2>
    
    <h4>@ViewBag.Name</h4>
    @Model.Name +  @Model.Age
    
    

    然后重启服务后,刷新页面,会看到类似的内容:

    image-20200601235928566

    3. 总结

    我们在这一篇介绍了视图的一些概念,并介绍了如何使用控制器给视图传递数据。下一篇将讲解一下路由的高级作用,如何通过路由携带数据。

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

    file

  • 相关阅读:
    Jmeter响应断言的处理。
    Jmeter超时处理。
    HTTP协议简介以及特点。
    自动化测试面试技巧。
    父类构造方法有无参数对子类的影响。
    自动化分层思想分析1.
    设计模式
    遍历课程列表代码。
    如何遍历当前页课程定位分析,以及代码编写。
    “笨方法”学习Python笔记(1)-Windows下的准备
  • 原文地址:https://www.cnblogs.com/c7jie/p/13034221.html
Copyright © 2020-2023  润新知