1 起個頭
很多95後的程序員沒有搞明白MVC,需要多練習才行。
MVC實際上不是設計模式,而是架構模式/體系結構模式,體系結構是老稱呼了,現在基本上都叫架構了。
模型-視圖-控制器 (MVC) 體系結構模式將應用分成 3 個主要組件:模型 (M)、視圖 (V) 和控制器 (C)。 MVC 模式有助於創建比傳統單片應用更易於測試和更新的應用。
模型 (M):表示應用數據的類。 模型類使用驗證邏輯來對該數據強制實施業務規則。 通常,模型對象檢索模型狀態並將其存儲在數據庫中。
視圖 (V):視圖是顯示應用用戶界面 (UI) 的組件。 此 UI 通常會顯示模型數據。
控制器 (C):處理瀏覽器請求的類。 它們檢索模型數據並調用返回響應的視圖模板。 在 MVC 應用中,視圖僅顯示信息;控制器處理並響應用戶輸入和交互。 例如,控制器處理路由數據和查詢字符串值,並將這些值傳遞給模型。 該模型可使用這些值查詢數據庫。
1.1 MVC優點
l MVC 模式可幫助創建分隔不同應用特性(輸入邏輯、業務邏輯和 UI 邏輯)的應用,同時讓這些元素之間實現鬆散耦合。
l 該模式可指定應用中每種邏輯的位置。 UI 邏輯位於視圖中。 輸入邏輯位於控制器中。 業務邏輯位於模型中。
l 這種隔離有助於控制構建應用時的複雜程度,因爲它可用於一次處理一個實現特性,而不影響其他特性的代碼。 例如,處理視圖代碼時不必依賴業務邏輯代碼
1.2 創建一個MVC項目
1.3 新增一個控制器
1.4 新增HTTP終結點調用
控制器中的每個 public 方法均可作爲 HTTP 終結點調用。
HTTP 終結點是 Web 應用程序中可定向的 URL(例如 https://localhost:44399/EdisonTest ),其中結合了所用的協議HTTPS 、TCP 端口等 Web 服務器的網絡位置 localhost:44399 ,以及目標 URI EdisonTest。
2 進一步
2.1 路由
MVC 根據入站 URL 調用控制器類(及其中的操作方法)。 MVC 所用的默認 URL 路由邏輯使用如下格式來確定調用的代碼:
/[Controller]/[ActionName]/[Parameters]
在 Startup.cs 文件的 Configure 方法中設置路由格式。
如果瀏覽到應用且不提供任何 URL 段,它將默認爲左邊紅線行中指定的“Home”控制器和“Index”方法。
第一個 URL 段決定要運行的控制器類。 localhost: 44399映射到 EdisonTestController 類。
第二個 URL段決定類上的操作方法。 localhost:44399/EdisonTest/GetOwnerName 將觸發 EdisonTestController 類的GetOwnerName 運行。 請注意,只需瀏覽到 localhost:xxxx/EdisonTest ,而GetOwnerName 方法默認調用。 原因是 GetOwnerName 是默認方法,如果未顯式指定方法名稱,則將在控制器上調用它。
第三個URL 段 ( id ) 針對的是路由數據。
測試:
2.2 增加參數
修改代碼,將一些參數信息從 URL 傳遞到控制器。
l 使用 C# 可選參數功能指示,未爲 numTimes 參數傳遞值時該參數默認爲 1。
l 使用 HtmlEncoder.Default.Encode 防止惡意輸入(即 JavaScript)損害應用。
l 在 $"I am Edison.Feng, you are {name}. Number of Times:{numTimes}"中使用內插字符串。
測試:
2.3 參數路由
參數也可以作爲路由:
測試:
問題1:路由的第三部分怎麼解析的?
問題2:路由的第三部分的問號表示什麼?
2.4 增加一個View視圖
目的:消除前面的硬編碼,不直接返回HTML文件內容,而是返回視圖對象:
l 使用 Razor 視圖文件來順利封裝爲客戶端生成 HTML 響應。
l 使用 Razor 創建視圖模板文件。 基於 Razor 的模板具有“.cshtml”文件擴展名。 它們提供了一種巧妙的方法來使用 C# 創建 HTML 輸出。
l 右鍵單擊“Views”文件夾,然後單擊“添加”>“新文件夾”,並將文件夾命名爲“EdisonTest”。
l 右鍵單擊“Views/EdisonTest”文件夾,然後單擊“添加”>“新項”。
l 在“添加新項 - MvcMovie”對話框中
l 在右上角的搜索框中,輸入“視圖”
l 選擇“Razor 視圖”
l 保持“名稱”框的值:getownername.cshtml。
l 選擇“添加”
修改視圖文件getownername.cshtml:
修改默認路由,Startup.cs:
修改控制器,增加一個get方法:
測試:
2.5 給視圖傳點數據
使用ViewData在視圖和控制器之間傳遞數據:
(1)修改控制器
(2)修改視圖
(3)測試
3 數據庫操作
3.1 將真實的數據存在數據庫中,並取出來
l 結合 Entity Framework Core (EF Core) 使用這些類來處理數據庫。 EF Core 是對象關係映射 (ORM) 框架,可以簡化需要編寫的數據訪問代碼。
l 要創建的模型類稱爲 POCO 類(源自“簡單傳統 CLR 對象”),因爲它們與 EF Core 沒有任何依賴關係。 它們只定義將存儲在數據庫中的數據的屬性。
3.2 新增一個模型Model
選中Models文件夾,右鍵菜單......
3.3 增加屬性
數據庫需要 Id 字段以獲取主鍵。
[DataType(DataType.Date)] :DataType 屬性指定數據的類型 ( Date )。
通過此特性:
用戶無需在數據字段中輸入時間信息。
僅顯示日期,而非時間信息。
DataAnnotations
3.4 “腳手架”工具
l 腳手架:Scaffold,或者翻譯爲基架
l .net core通過腳手架工具(Scaffolded Item)生成頁面,用於對模型Model執行創建、讀取、更新和刪除 (CRUD) 操作
3.5 使用EF Core的視圖
l 模型類:選擇剛剛建好的模型類Movie
l 數據Context類:新建,默認命名爲MvcMovie1Context
l 視圖:默認
l 控制器名稱:默認
3.6 “搭建基架”過程自動創建哪些文件?
l EF Core數據庫Context類
l 控制器
l Razor視圖文件(CRUD)
l Create
l Index
l Details
l Edit
l Delete
3.7 EF Core遷移功能
不使用EFCore遷移功能,只“搭建基架”則程序運行提示SqlException:不能打開數據庫
l 初始遷移
l 進入PMC(即程序包管理控制檯)
l 輸入Add-Migration Initial並回車,生成用於創建初始數據庫架構的代碼,數據庫架構基於在 MvcMovieContext 類中指定的模型。Initial 參數是遷移名稱
l 輸入Update-Database並回車,在 Migrations/{time-stamp}_InitialCreate.cs 文件中運行 Up 方法。Migrations/{time-stamp}_InitialCreate.cs用於創建數據庫
l 依賴注入
l 腳手架工具已經把數據上下文類MvcMovie1Context注入到容器services中
l AddDbContext 指定數據庫和連接字符串
l =>是Lambda運算符
l 數據上下文類爲 Movie 模型協調 EF Core 功能
l (創建、讀取、更新、刪除等)
l 實體集DbSet對應數據庫的數據表
l 通過調用 DbContextOptions 對象中的一個方法將連接字符串名稱傳遞到上下文。
l 進行本地開發時, ASP.NET Core 配置系統 在 appsettings.json 文件中讀取數據庫連接字符串。
3.8 CRUD: Details
l Details方法
l 將強類型模型對象傳遞給視圖:憑藉此強類型方法可更好地對代碼進行編譯時檢查
l FirstOrDefaultAsync返回滿足條件的第一個元素,或者在不滿足條件下的默認元素
l m => m.Id == id 元素的ID等於給定的ID
l Details.cshtml
l @model MvcMovie1.Models.Movie
l 通過將 @model 語句包括在視圖文件的頂端,
l 可以指定視圖期望的對象類型
3.9 CRUD: Index
l Index方法
l ToListAsync異步創建一個List
l Index.cshtml
3.10 CRUD: Edit
3.11 CRUD: Create
3.12 CRUD: Delete
4 擴展更多的
4.1 數據庫連接字符串
l DbContextOptionsBuilder.UseSqlServer
l IConfiguration.GetConnectionString
l AppSettings.json
3.2 SQL Server Express LocalDB
l SQL Server對象資源管理器
l 視圖設計器
l 查看數據
4.3 數據庫種子
l 數據庫種子:沒有任何數據時初始化數據
l 修改Main方法
l 增加SeedData類
測試:
l 刪除數據庫的數據之後測試,如圖。
l 刷新數據庫後查看數據
4.4 修改顯示列表
l 修改列Title。
l 修改列數據顯示格式
4.5 按標題搜索
l 給Index操作增加一個參數。
l s => s.Title.Contains() 代碼是 Lambda 表達式
l Lambda 表達式在基於方法的 LINQ 查詢中用作標準查詢運算符方法的參數,如 Where 方法或 Contains,在對 LINQ 查詢進行定義或通過調用方法(如 Where、Contains 或 OrderBy)進行修改前不會被執行。這意味着表達式的計算會延遲,直到真正循環訪問其實現的值或者調用 ToListAsync 方法爲止。
l Contains 方法在數據庫上運行,而不是在 C# 代碼中運行
l 在cshtml中綁定兩個input標籤。
l <form> 標記使用表單標記幫助器,提交表單時篩選器字符串會發布到電影控制器的 Index 操作。
l 增加一個POST Index操作
l 測試
l 不再出現過濾頁面
l 修改index.cshtml
l 測試:能夠轉到過濾頁面
4.6 按流派搜索
l 修改index操作方法
l System.linq命名空間,有兩個靜態類:Queryable和Enumerable
l IQueryable:where條件接收表達式,延遲執行
l IEnumerable:where條件接收一個謂詞表達式(委託),立即執行
l SelectList是SelectListItem的集合,和<select>標籤聯合使用
l 修改index.cshtml
l 最上面一句改爲:@model MvcMovie1.Models.GenreViewModel
l 在Title: <input......上面增加:
l <select asp-for="MovieGenre" asp-items="Model.Genres">
l <option value="">all</option>
l </select>
l 修改Title: <input......爲Title: <input type="text" asp-for="searchString">
l 把model.Title改爲model.Movies[0].Title
l 把model.ReleaseDate改爲model.Movies[0].ReleaseDate
l 把model.Genre改爲model.Movies[0].Genre
l 把model.Price改爲model.Movies[0].Price
l 把@foreach (var item in Model) {改爲@foreach (var item in Model.Movies) {
4.7 增加新屬性
l 修改Models/Movie.cs
l 修改控制器
l 更新Create方法的[Bind]屬性
l 更新Edit方法的[Bind]屬性
l 修改Views/Movies/Index.cshtml
l 更新 /Views/Movies/Create.cshtml
l 更新 /Views/Movies/Edit.cshtml
l 更新 SeedData 類
l 更新數據庫
l 讓EF Core重建數據庫
l 對數據庫直接修改表結構
l 使用Code First遷移(將新字段添加到模型,將新字段遷移到數據庫)
l 進入PMC
l 執行Add-Migration Rating
l Add-Migration 命令會通知遷移框架使用當前 Movie DB 架構檢查當前 Movie 模型,並創建必要的代碼,將 DB 遷移到新模型。
l 名稱“Rating”是任意的,用於對遷移文件進行命名。 爲遷移文件使用有意義的名稱是有幫助的。
l 執行Update-Database
l 如果刪除 DB 中的所有記錄,初始化方法會設定 DB 種子,並將包括 Rating 字段。
4.8 預校驗
如下圖,有如下幾種標註:
l Required
l 必需,缺少則返回400錯誤
l MinimumLength
l 最小長度
l RegularExpression
l 正則表達式
l Range
l 範圍
l StringLength
l 字串長度
l DataType
l 數據類型
l 需要禁用 jQuery 日期驗證才能使用具有 DateTime 的 Range 特性
DRY原則是非常有用的: