參考文檔:Getting started with ASP.NET Core MVC and Visual Studiohtml
這系列文章是參考了.NET Core文檔和源碼,可能有人要問,直接看官方的英文文檔不就能夠了嗎,爲何還要寫這些文章呢?程序員
緣由以下:數據庫
- 官方文檔涉及的內容至關全面,屬於那種大而全的知識倉庫,不太適合初學者,很容易讓人失去重要,讓人掉入到具體的細節之中。
- 對於大多數人來說開發語言只是工具,程序員都有一個通病,就是死磕工具,把工具學深。我認爲在工具上沒有必要投入太多時間,以能高效地完成平常的工做項目爲準便可。要需求驅動學習,你須要什麼學什麼。若是你學的新技術新特性只是屠龍之技或者只須要用到的時候去查一下便可的話,這種死磕這又有什麼用。沒有必要花120%的時間去學100%的知識,你只須要花20%的時間去學習80%的知識就能夠了,剩下的等實際的項目中用到的時候去查就能夠了,工具只是工具,不是工做自己。
- 目前基本全部的文章都是基於Windows平臺的Visual Studio IDE來介紹的。而我用的是一臺Mac,因此我將基於Mac平臺的Visual Studio Code講解適合咱們實際項目中遇到的知識。
- 還有一點,就是這是我我的的學習總結。
這系列文章就是讓你去花20%的時間去學80%的東西,剩下的20%再去看官方文檔。瀏覽器
以前介紹了《如何在Mac下運行ASP.NET Core應用程序》,主要是講解了如何在Mac下把ASP.NET Core跑起來,在這一篇中將進一步分析如何添加Controller、View、Model等。架構
Model-View-Controller (MVC)架構模式將一個應用程序分紅了三大塊:Model、View、Controller。mvc
User
Model 從數據庫獲取用戶數據,並將它交給View來顯示或者直接更新,更新後的數據再寫入到數據庫中。MVC模式幫助你建立一個關注分離的應用程序(輸入邏輯、業務邏輯、UI邏輯),同時這個模塊之間是鬆耦合的。UI邏輯屬於View,輸入邏輯屬於Controller,業務邏輯屬於Model。app
namespace MyFirstApp.Controllers { public class HomeController : Controller { // GET: /<controller>/ public IActionResult Index() { return View(); } // GET: /<controller>/About public IActionResult About() { ViewData["Message"] = "Your application description page."; return View(); } public IActionResult Contact() { ViewData["Message"] = "Your contact page."; return View(); } public IActionResult Error() { return View(); } public IActionResult Welcome(string name, int id = 1) { ViewData["Message"] = "Hello " + name; ViewData["id"] = id; return View(); } } }
在控制器中的每個public
方法均可以做爲HTTP終結點被調用。asp.net
第一個註釋表示這是一個經過在根URL添加「/Home/」進行調用的HTTP GET方法。第二個註釋表示這是一個經過在根URL添加"/Home/About/"來進行調用的HTTP GET方法。工具
MVC根據傳入的請求URL調用相應的控制器類以及其中的Action方法,MVC默認使用的URL路由邏輯採用相似於這樣的格式來決定具體的代碼調用:佈局
/[Controller]/[ActionName]/[Parameters]
打開Startup.cs
你會看到該項目的路由規則:
當你不帶任何URL段(segment)直接運行該程序時,將默認訪問「Home」控制器中的"Index"方法。
第一個URL segment決定運行哪一個Controller,因此http://localhost:5000/Home
映射到HomeController
類;URL segment第二個部分決定類裏面的Action方法。因此http://localhost:5000/Home/Index
會運行HomeController
類中的Index
方法;URL segment的第三部分(id
)是路由數據。
這裏經過增長一個方法來顯示經過URL傳遞一些參數信息到Controller。
public string Welcome(string name, int id = 1) { return HtmlEncoder.Default.Encode($"Hello {name}, id: {id}"); }
上述代碼經過使用HtmlEncoder.Default.Encode
來保護應用免受JS的惡意輸入,而且使用了C#的新特性Interpolated Strings。
http://localhost:5000/Home/Welcome?name=Charlire&id=1
MVC的模型綁定系統自動將查詢字符串的命名參數映射到具體的方法中的參數,注意名稱必須一致。
上述代碼中URL segment(Parameters
)沒有被使用到,參數name
和id
都是做爲查詢字符串被傳遞的。?
是一個分隔符,後面跟着的就是查詢字符串,&
用來分割查詢字符串。
輸入下面的URL:http://localhost:5000/Home/Welcome/1?name=Charlire
。這一次第三個URL segment將匹配到路由參數id
。Welcome
方法包含一個與MapRoute
方法中的URL模板相匹配的id
參數。隨後的?
(id?
)表示id參數是可選的。
經過Razor視圖引擎建立視圖模板文件,基於Razor的視圖模板使用 .cshtml 做爲文件擴展名,經過使用C#提供了一個優雅的方式來建立HTML。
public IActionResult Index() { return View(); }
上面的Index
方法使用視圖模板來生成一個HTML響應給瀏覽器。Controller中的Action方法一般返回一個IActionResult
(或一個派生於ActionResult
類),而不是像String這樣的基元類型。
點擊Views文件夾,在該文件夾下面新建與Controller名對應的文件夾。
而後咱們導航到Views->User文件夾,運行命令yo aspnet:mvcview Index
在該文件夾下面生成Index.cshtml。
Index
方法只是簡單地運行了return View()
,來指定方法去使用一個視圖模板文件來爲瀏覽器渲染最新的響應。由於沒有顯式指定所要使用的視圖模板文件,MVC會默認使用 /Views/User 文件夾中的 Index.cshtml。
通用點擊菜單連接,你會發現每個頁面都顯示了相同的菜單佈局,這個菜單佈局位於 *Views/Shared/_Layout.cshtml* 文件。
Layout模板容許你在一個地方指定網站的HTML容器佈局,並應用到網站的多個頁面中。@RenderBody()
是一個佔位符,用來顯示你指定視圖的位置,「包裹在」佈局頁面。舉個例子,當你點擊About連接,Views/Home/About.cshtml視圖就會在RenderBody
方法內渲染。
注意如今每個頁面都顯示了新修改的連接,經過在Layout模板中修改一次,網站上的全部的頁面都當即顯示成新修改的信息。
經過查看 *Views/_ViewStart.cshtml* 文件:
@{ Layout = "_Layout"; }
*Views/_ViewStart.cshtml* 文件將 *Views/Shared/_Layout.cshtml* 文件引入到每個視圖中。你能夠經過Layout
屬性來設置一個不一樣的佈局視圖,或將它設置成null
,那麼將不使用任何一個佈局文件。
修改 Views/User/Index.cshtml 文件以下:
@{ ViewData["Title"] = "User List"; } <h2>User List</h2> <p>Hello from View Template!</p>
ViewData["Title"] = "User List";
將ViewDataDictionary
的Title
屬性設置爲User List
。這個Title
屬性將用在 *Views/Shared/_Layout.cshtml* Layout頁面的<title>
HTML元素上。
<title>@ViewData["Title"] - User MVC Application</title>
注意 Index.cshtml 視圖模板中的內容是怎麼和 *Views/Shared/_Layout.cshtml* 視圖模板進行合併的,佈局模板使得修改應用裏全部的頁面很容易。
在談到數據庫和模型(Models)以前,先讓咱們討論一下從控制器傳遞信息到視圖。控制器方法會在傳入的URL請求響應時被調用。控制器類是用於處理傳入的瀏覽器請求,從數據庫獲取數據,並最終決定哪一種類型的的響應會被回傳給瀏覽器。
控制器主要負責提供視圖模板向瀏覽器呈現一個響應所需的數據或對象。
最佳實踐:視圖模板不該該執行業務邏輯或直接與數據庫進行交互,而只應該使用控制器提供給它的數據。保持這樣的「關注分離」有助於保持你的代碼整潔,可測試性及更易於維護。
當前,HomeController
控制器中的Welcome
方法接受一個name
、id
參數,而後直接將值輸出到瀏覽器。咱們在控制器中將使用一個視圖模板來代替字符串,視圖模板將生成一個動態響應,這就意味着你須要經過控制器傳遞適當的數據給視圖來生成響應,可讓控制器將視圖模板須要的動態數據(參數)放入ViewData
字典中,隨後視圖模板能夠經過訪問該字典獲取到這些數據。
ViewData
字典是一個動態對象,你能夠將任何你想要的數據加進去。在你加入數據以前,ViewData
對象沒有任何已定義的屬性。MVC的模型綁定系統自動映射地址欄中查詢字符串的命名參數到你方法中的參數。
public IActionResult Welcome(string name, int id = 1) { ViewData["Message"] = "Hello " + name; ViewData["id"] = id; return View(); }
ViewData
字典對象包括將要傳遞到視圖的數據。接受,咱們來建立一個Welcome
視圖模板。
這裏將在Welcome.cshtml視圖模板中建立一個循環。
@* For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 *@ @{ ViewData["Title"]= "Welcome Page"; } <h2>Welcome</h2> <ul> @for(int i=0; i<(int)ViewData["id"]; i++) { <li>@ViewData["Message"]</li> } </ul>
數據從URL得到並經過MVC模型綁定器傳遞到控制器,控制器將數據打包封裝到ViewData
字典中並將該對象傳遞給視圖。接着,視圖將數據以HTML的形式渲染到瀏覽器。
咱們使用了一個ViewData
字典來將數據從控制器傳遞到視圖,ViewData
字典是一個動態對象,它提供了一種便捷的後期綁定方式來傳遞信息給視圖。接下來咱們將使用視圖模型(View Model)來實現相同的目的。經過View Model來傳遞數據比經過ViewData
更受歡迎。