♣ 視頻地址:https://www.bilibili.com/video/av38392956/?p=7html
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,而後傳遞給Viewide
咱們新給Student類加了一個屬性BirthDate,以下圖函數
而且在服務裏面把這個屬性加上,以下圖spa
而後咱們創建ViewModels的文件夾,而且添加一個類再添加三個屬性,這個類是給HomeController裏Index用的,以下圖3d
接下來咱們回到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); }
而後回到視圖,修改下代碼後運行,看到效果出來了以下圖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); }
而後回到視圖裏,把上面的集合改成一個類,下面這接用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; } }
如今咱們創建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); }
而且在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,以下圖