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,如下图

 

posted @ 2019-07-15 16:57  大北票  阅读(186)  评论(0编辑  收藏  举报