• 8:View的Model和Tag Helpers


    ♣ 视频地址:https://www.bilibili.com/video/av38392956/?p=7

    VIEWMODEL,首先讲下概念:

      我们通常有数据库的Model,通常叫Entity Model(使用EF和EF Core都知道),数据库里的字段在Model里都有一个类,里面的属性是一一对应的,比如FirstName,LastName,BirthDate

      但是我们Controller想返回一个视图,视图所需要的信息并不是上面三个字段的原始信息,它需要完成的名字Name,需要一个年龄Age而不是出生日期,所以我们给这个View返回的Model最好是Name和Age,那我们就新建一个Model就叫View Model,也可以叫DTO(Data Transfer Object)数据转换的对象

      而我们再Controller里所做的就是把左边的Model转化为右边的Model,然后传递给View

    我们新给Student类加了一个属性BirthDate,如下图

    并且在服务里面把这个属性加上,如下图

    然后我们建立ViewModels的文件夹,并且添加一个类再添加三个属性,这个类是给HomeController里Index用的,如下图

    接下来我们回到Controller,把vms传给View当参数

    public IActionResult Index()
            {
                var list = _repository.GetAll();
                //Select =>将序列的每个元素投影到新表单中,在这里就是HomeIndexViewModel
                var vms = list.Select(x => new HomeIndexViewModel
                {
                    Name = $"{x.FirstName}{x.LastName}",
                    //当前时间减去x.BirthDate,得出来的天数除以365
                    Age = DateTime.Now.Subtract(x.BirthDate).Days / 365
                });
    
                return View(vms);
            }
    View Code

     然后回到视图,修改下代码后运行,看到效果出来了如下图


    接下来我们进一步改进下代码

    现在我们传进来是个集合,类型是HomeIndexViewModel,但是这样并不特别正确,最好的方法是这样,我们建一个StudentViewModel把HomeIndexViewModel的属性给它,如下图

    然后HomeIndexViewModel里改为下面这样

    接着我们回到HomeController,改一下我们的代码

     public IActionResult Index()
            {
                var list = _repository.GetAll();
                //Select =>将序列的每个元素投影到新表单中,StudentViewModel
                var vms = list.Select(x => new StudentViewModel
                {
                    Id = x.Id,
                    Name = $"{x.FirstName}{x.LastName}",
                    //当前时间减去x.BirthDate,得出来的天数除以365
                    Age = DateTime.Now.Subtract(x.BirthDate).Days / 365
                });
                var vm = new HomeIndexViewModel
                {
                    Students = vms
                };
                return View(vm);
            }
    View Code

     然后回到视图里,把上面的集合改为一个类,下面这接用Model.Students即可,运行看到也可以,如下图


    下面做第二个需求,我们把名字当做超链接,然后点击名字,转到学生的属性信息页面...

    首先我们先写Action,传入一个id,根据id来找我们的学生

       public IActionResult Detail(int id)
            {
                var student = _repository.GetById(id);
                return View(student);
            }

    接着,我们去建接口,接口的返回类型为T,如下图

    然后我们去实现这个接口,这里我把学生信息提到构造函数里了

    public class InMemoryRepository : IRepository<Student>
        {
            private readonly List<Student> _students;
            public InMemoryRepository()
            {
                _students =  new List<Student>
                {
                    new Student
                    {
                        Id = 1,
                        FirstName = "Nick",
                        LastName = "Carter",
                        BirthDate =new DateTime(1980,1,4)
                    },
                    new Student
                    {
                        Id = 2,
                        FirstName = "Kevin",
                        LastName = "Richardson",
                        BirthDate =new DateTime(1974,6,16)
                    },
                    new Student
                    {
                        Id = 3,
                        FirstName = "Howie",
                        LastName = "D",
                        BirthDate =new DateTime(1978,12,5)
                    }
                };
            }
            public IEnumerable<Student> GetAll()
            {
                return _students;
            }
    
            public Student GetById(int id)
            {
                Student st = _students.FirstOrDefault(s => s.Id == id);
                return st;
            }
        }
    View Code

     现在我们建立Detail视图,如下图

    我们先使用路由试一下,结果好用,如下图

    我们用queryString,查询字符串的方式试一下,结果也好用,如下图

    那如果路由里面有id,后面又加上querystring,它显示那个呢?显示路由对应的,如下图

     现在有3个学生,那我们在路由里输入5呢,当然是报空指针异常的错啦,因为Model为Null,所以Null.FirstName就会发生空指针异常,如下图

     这时候我们应该判断Model是否为Null,可以在View里判断,但最好的方式是在Controller里判断

          public IActionResult Detail(int id)
            {
                var student = _repository.GetById(id);
                if (student == null)
                {
                    //如果student为null,怎定向到HomeController下的Index方法
                    return RedirectToAction("Index");
                }
                return View(student);
            }
    View Code

    并且在Index视图里加上超链接,如下图

     这时候再试试如果在路由里输入id为5,可以看到重新定向到Index页面了

    那上面的超链接呢是比较低级的写法,既然我们用了MVC框架,那么MVC里面肯定有些东西来帮助我们建立超链接

     下图就是MVC里的写法,第一个参数是超链接的名字,第二个参数是action的名字,第三个是参数id,如果这样写,那么它就会找视图对应的Controller里的Action

     

    如果你想让它跳转到其他的Controller对应的Action,只需要在后面再加一个Controller的参数即可,如下图


    上面看到了两个写法,那么还有一个是ASP.NET Core出现之后的叫Tag Helpers(上面叫做Html Helpers...),我们接下来使用Tag Helpers来操作

    使用Tag Helpers之前需要进行引用,首先需要在Views文件夹下面添加_ViewImports.cshtml,如下图

     咱们先不管这个文件具体是做什么的,这个View不渲染任何东西,它在这里就相当于提供了一些指令,告诉Razor引擎这些视图应该怎么被渲染,并且这些View应该有哪些功能,有点引用的意思

    我们在里面写上下面这一段,意思就是我想把Microsoft.AspNetCore.MVC.TagHelpers这个Assembly里面所有的TagHelper在我们所有的视图里可以使用的话,加上*,就这么写就可以了

    接下来我们回到index视图页面,如下图asp-开头的就是ASP.NET Core 里面超链接的Helper,虽然它看起来像Html元素的属性,其实不是

    MVC框架Razor引擎,它在服务端看到这个东西的时候(在这里就是超链接),它就会对它进行处理,渲染,在服务器端给它处理掉,然后返回客户就是Html

     

    然后我们在明细页加一个返回,也用Tag Helper,如下图

  • 相关阅读:
    Python学习笔记 第四天
    Python学习笔记 第三天
    linux系统优化(CentOS7)
    ARMS踩坑合集
    zabbix报错合集(附解决方法)
    keepalived
    ansible
    nginx
    安装虚拟机
    linux发展、redhat与centos的区别
  • 原文地址:https://www.cnblogs.com/Codemandyk/p/11009665.html
Copyright © 2020-2023  润新知