前面三章已經把MVC啟動過程以及源代碼做了講解,本章開始正式MVC,mvc全稱叫model view controller,也就是把表現層又細分三層,官網的圖片描述: 預設創建了一個.net core web 項目,把Startup類中的代碼改成下麵這樣 我們.net core mvc是基於約定的一 ...
前面三章已經把MVC啟動過程以及源代碼做了講解,本章開始正式MVC,mvc全稱叫model view controller,也就是把表現層又細分三層,官網的圖片描述:
預設創建了一個.net core web 項目,把Startup類中的代碼改成下麵這樣
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment environment) { if (environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvcWithDefaultRoute(); } }
我們.net core mvc是基於約定的一種模式,例如:控制器是放在Controllers文件夾中的(當然這不是必須),視圖放在pages或者views文件夾中等,首先我們講講Controller的約定,先不管例外的情況,我們要定義一個Controller首先要繼承至Microsoft.AspNetCore.Mvc.Controller類並且符合下麵其中之一的條件:
1、這個類名稱尾碼是以Controller結尾
例如:新建一個Home類,那麼它的簽名應該像這樣:public class HomeController : Controller
2、繼承至帶有Controller尾碼名的基類,
例如:你已經創建好了一個BaseController基類,現在需要創建Home類,那麼他的簽名可以是這樣:public class Home : BaseController
3、這個類帶有[Controller]標簽
例如:新建一個Home類,那麼它的簽名應該像這樣:
[Controller]
public class Home : Controller
在Controller類裡面寫的方法,我們稱為Action,例如下麵,這就創建了一個名為Index的方法, 返回值類型是一個實現了IActionResult介面的實例,這裡返回的是View
public class HomeController: Controller { public IActionResult Index() { return View(); } }
在這裡先說說View()這個方法到底幹了什麼事兒吧,我們轉到源代碼可以看到最終View是創建了一個ViewResult這個類,這個類又繼承至ActionResult並且實現了IActionResult介面,其中最主要 ExecuteResultAsync方法就是返回給我們前端的數據,ViewResult這個類中有兩個我們常用的屬性,分別是ViewName和ViewData,分別代表"視圖的名稱"和"視圖需要的數據",如果視圖名稱不傳那麼就約定以控制器Action名稱為準,否則已傳入名稱為準,如果傳入ViewData那麼就可以在視圖中的Model屬性裡面訪問到傳入的數據,並且轉換為強類型,就以上面的例子,我們在Views文件夾中創建一個Home文件夾和Index.cshtml視圖文件,並且在Models文件夾中創建兩個實體,一個為通用的ViewModel,代碼如下:
public class ViewModel<T> where T : class { public string Title { get; set; } public IEnumerable<T> Data { get; set; } }
另一個是具體的Action視圖所需的數據實體,所以名稱為IndexModel,具體代碼如下:
public class IndexModel { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } }
另外我們再寫一個獲取Index數據的服務,名稱為HomeService,並且在Startup類的ConfigureServices方法中最前面加上services.AddScoped<HomeService>();
先不管是否符合設計規範,這樣做完後我們就可以在其他實體中註入HomeService的實例了,我們HomeService中代碼可以是這樣的:
public class HomeService { private IEnumerable<IndexModel> _sourceData = new List<IndexModel> { new IndexModel { Id = 1, Description = "my is code1", Name = "test1" }, new IndexModel { Id = 2, Description = "my is code2", Name = "test2" }, new IndexModel { Id = 3, Description = "my is code3", Name = "test3" }, new IndexModel { Id = 4, Description = "my is code4", Name = "test4" }, new IndexModel { Id = 5, Description = "my is code5", Name = "test5" }, }; public ViewModel<IndexModel> GetData(int id) { return new ViewModel<IndexModel> { Title = "Index", Data = id > 0 ? _sourceData.Where(x => x.Id == id) : _sourceData }; } }
這個時候將HomeController中的代碼改成這樣
public class HomeController: Controller { private readonly HomeService _service; public HomeController(HomeService service) { _service = service; } public IActionResult Index() { var data = _service.GetData(); return View(data); } }
然後轉到視圖文件,視圖中代碼如下:
@model ViewModel<IndexModel>; @{ ViewData["Title"] = Model.Title; } <ul> @foreach (var item in Model.Data) { <li> <span>名稱:@item.Name</span> <span>說明:@item.Description</span> <a asp-action="details" asp-route-id="@item.Id">詳細</a> </li> } </ul>
在視圖裡面有一句代碼值得註意
<a asp-action="details" asp-route-id="@item.Id">詳細</a>
這個是.net core改進部分,它叫做 TagHelpers,它是由.net core解析,最終變成正常的src屬性或者其他html屬性,這樣做的好處是更加接近於html本身的編程方式,
這裡有註意到我們定義的asp-action="details"表示的是轉到當前視圖的控制器details方法中,最終會生成的url path是這樣 /home/details?id={id},
為了能夠正常的運行,我們需要創建一個details方法,代碼如下:
public IActionResult Details(int id) { var data = _service.GetData(id);
data.Title = "Details"; return View(data); }
在創建details的視圖文件,代碼如下:
@model ViewModel<IndexModel> @{ ViewData["Title"] = Model.Title; var data = Model.Data.FirstOrDefault(); } <p>@data.Name,@data.Description,@data.Id</p>
然後我們運行程式,會看到如下界面:
點擊"詳細" 會出現以下界面:
好啦,mvc大致情況就介紹到這裡,後面會詳細說說Views這個文件夾中的一些規則以及,有興趣的也可以去官網看看https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/?view=aspnetcore-2.2&tabs=visual-studio