五月中旬 .NET Core RC2 如期發佈,我們遂決定翻譯 ASP.NET Core 文檔。我們在何鎮汐先生、悲夢先生、張仁建先生和雷歐納德先生的群中發佈了翻譯計劃招募信息,並召集到一群小伙伴。我們從六月開始翻譯文檔,目前已完成前兩章,並將按計劃以連載的方式逐篇公佈。當翻譯計劃完成後,所有文檔將... ...
原文:Adding a model
作者:Rick Anderson
翻譯:婁宇(Lyrics)
校對:許登洋(Seay)、孟帥洋(書緣)、姚阿勇(Mr.Yao)、夏申斌
在這一節里,你將添加一些類來管理資料庫中的電影數據。這些類將成為 MVC 應用程式中的 “Model” 部分。
你將使用 .NET Framework 中名為 Entity Framework Core 的資料庫訪問技術來定義和使用這些數據模型類。Entity Framework Core (通常被稱為 EF Core) 有一種具有特色的被稱為 Code First 的開發模式。你先編寫代碼,然後通過這些代碼創建資料庫表。 Code First 允許你通過編寫一些簡單的類(也被稱為 POCO 類, "plain-old CLR objects." )來創建數據模型對象,然後根據你的類創建資料庫。如果你需要先創建資料庫,你仍然可以按照本教程來學習 MVC 和 EF 應用程式開發。
添加數據模型類
在解決方案資源管理器中,右鍵點擊 Models 文件夾 > 添加 > 類 。將類名命名為 Movie 並且添加以下屬性:
using System;
namespace MvcMovie.Models
{
public class Movie
{
public int ID { get; set; } //手動高亮
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}
除了你用來構造電影的屬性,還需要一個 ID 欄位來作為資料庫主鍵。生成項目。如果你沒有生成這個應用程式,你將在下一節中遇到錯誤。我們終於為這個 MVC 應用程式添加了一個 Model 。
通過基架生成一個控制器(Controller)
在 解決方案資源管理器 中,右鍵點擊 Controllers 文件夾 > 添加 > 控制器
在 添加基架 對話框中,點擊 MVC Controller with views, using Entity Framework > 添加 。
完成 添加控制器(Add Controller) 對話框
- 模型類(Model class): Movie(MvcMovie.Models)
- 數據上下文類(Data context class): ApplicationDbContext(MvcMovie.Models)
- 視圖(Views): 保持預設的選項
- 控制器名稱(Controller name): 保持預設的 MoviesController
- 點擊 添加(Add)
Visual Studio 基架引擎創建的東西如下:
- 一個電影控制器(Controller)(Controllers/MoviesController.cs)
- Create、Delete、Details、Edit 以及 Index 的 Razor 視圖文件(Views/Movies)
Visual Studio 為你自動創建 CRUD(創建、讀取、更新以及刪除)Action 方法和視圖(View)(自動創建 CRUD Action 方法和 View 視圖被稱為 搭建基架(scaffolding))。很快你將擁有一個可以讓你創建、查看、編輯以及刪除電影條目的完整功能的 Web 應用程式。
運行這個應用程式並且點擊 Mvc Movie 鏈接。你將遇到以下錯誤:
這是一個很棒的錯誤消息,我們將通過這些指令準備好電影應用程式的資料庫。
使用數據遷移來創建資料庫
在項目文件夾(MvcMovie/src/MvcMovie)打開命令提示符。按照以下說明,以一個快捷的方式打開項目文件夾
- 打開一個在項目根目錄下的文件(在這個例子中,使用 Startup.cs )。
右鍵點擊 Startup.cs > 打開所在的文件夾(Open Containing Folder) 。
- Shift + 右鍵點擊一個文件夾 > 在此處打開命令視窗(Open command window here)
運行
cd ..
將路徑退回項目文件夾在命令提示符中運行以下命令:
dotnet ef migrations add Initial
dotnet ef database update
dotnet
(.NET Core) 是 .NET 的跨平臺實現。你可以在這裡瞭解它。dotnet ef migrations add Initial
運行 Entity Framework .NET Core CLI 遷移命令並創建初始化遷移。參數 "Initial" 可以是任意值,但是通常用這個作為第一個(初始的) 資料庫遷移。這個操作創建了一個 Data/Migrations/2016_Initial.cs 文件,這個文件包含了添加(或刪除)Movie
表到資料庫的遷移命令。dotnet ef database update
dotnet ef database update 用我們剛剛創建的遷移來更新資料庫。
測試一下
- 運行應用程式並點擊 Mvc Movie 鏈接
- 點擊 Create New 鏈接並創建電影
註意
你也許不能在Price
欄位中輸入小數點或逗號。為了實現對非英語環境中用逗號(",")來表示小數點,以及非美國英語日期格式的 jQuery 驗證,你必須採取措施國際化你的應用程式。查看額外的資源獲取更多的信息。現在僅僅輸入完整的數字,比如10。
點擊 Create 提交表單到伺服器,將電影數據保存到資料庫中。然後重定向到 /Movies
URL ,你可以在列表中看到新創建的電影。
再創建幾個電影條目。嘗試 Edit 、 Details 、 Delete 鏈接來執行各個功能。
檢查生成的代碼
打開 Controllers/MoviesController.cs 文件並檢查生成的 Index
方法。 MoviesController 中包含 Index
方法的部分如下所示:
public class MoviesController : Controller
{
private readonly ApplicationDbContext _context;
public MoviesController(ApplicationDbContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
構造函數使用依賴註入將資料庫上下文註入到控制器(Controller)。 數據上下文在控制器(Controller)中被用來執行增刪改查(CRUD)方法。
一個到 MoviesController 的請求從 Movies
表返回所有的條目,然後傳遞數據到 Index
視圖 (View) 。
強類型模型與 @model 關鍵字
在之前的教程中,你看到了控制器(Controller)如何通過 ViewData
字典傳遞數據到一個視圖模板 (View Template)。ViewData
字典是一個動態類型對象,它提供了一種便捷的後期綁定方式將信息傳遞給視圖。
MVC 也提供了傳遞強類型數據給視圖模版的能力。這種強類型的方式可以提供給你更好的代碼編譯時檢查,併在 Visual Studio(VS) 中具有更豐富的智能感知。VS 中的基架機制在為 MoviesController
類創建方法(Action)和視圖(View)的時候就對採用了這種方式(即,傳遞強類型模型)。
檢查在 Controllers/MoviesController.cs 文件中生成的 Details
方法:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
id
參數一般作為路由數據傳遞,例如 http://localhost:1234/movies/details/1
將:
- Controller 設置為
movies
(對應第一個 URL 段) - Action 設置為
details
(對應第二個 URL 段) - id 設置為 1(對應最後一個 URL 段)
你也可以向下麵一樣通過查詢字元串(Query String)傳遞 id
:
http://localhost:1234/movies/details?id=1
如果電影被找到了, Movie
模型(Model)的實例將被傳遞給 Details
視圖(View)。
return View(movie);
檢查 Views/Movies/Details.cshtml 文件的內容:
@model MvcMovie.Models.Movie <!--手動高亮-->
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Movie</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Genre)
</dt>
<dd>
@Html.DisplayFor(model => model.Genre)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd>
@Html.DisplayFor(model => model.Price)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ReleaseDate)
</dt>
<dd>
@Html.DisplayFor(model => model.ReleaseDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
@Html.DisplayFor(model => model.Title)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.ID">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>
通過在視圖模板(View Template)文件頂部加入一個 @model
語句,你可以指定視圖(View)所期望的對象類型。當你創建這個 MoviesController 時, Visual Studio 自動在 Details.cshtml 頂部加入了 @model
語句後面的部分。
@model MvcMovie.Models.Movie
@model
指令允許你訪問從控制器(Controller)傳遞給視圖(View)的這個強類型電影 Model
對象。例如,在 Details.cshtml 模板中,代碼用強類型 Model
對象傳遞所有的電影欄位到 DisplayNameFor
和 DisplayFor
HTML 幫助類(HTML Helper)里。 Create
和 Edit
方法和視圖模板(View Template)也傳遞一個 Movie
模型(Model)對象。
檢查 Index.cshtml 視圖模板(View Template)和 MoviesController 里的 Index
方法。註意觀察代碼在調用 View 方法時,是如何創建一個 列表(List)
對象的。這段代碼將 Movies
列表從 Index
Action 方法傳遞給視圖(View):
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
當你創建這個 MoviesController 時,Visual Studio 自動在 Index.cshtml 頂部加入以下 @model
語句:
@model IEnumerable<MvcMovie.Models.Movie>
@model
指令允許你訪問電影列表這個從控制器(Controller)傳遞給視圖(View)的強類型 Model
對象。例如,在 Index.cshtml 模板中,代碼通過 foreach
語句遍歷了電影列表這個強類型的 模型(Model)
對象:
@model IEnumerable<MvcMovie.Models.Movie> <!--手動高亮-->
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) { <!--手動高亮-->
<tr>
<td>
@Html.DisplayFor(modelItem => item.Genre) <!--手動高亮-->
</td>
<td>
@Html.DisplayFor(modelItem => item.Price) <!--手動高亮-->
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate) <!--手動高亮-->
</td>
<td>
@Html.DisplayFor(modelItem => item.Title) <!--手動高亮-->
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> | <!--手動高亮-->
<a asp-action="Details" asp-route-id="@item.ID">Details</a> | <!--手動高亮-->
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a> <!--手動高亮-->
</td>
</tr>
}
</tbody>
</table>
因為 模型(Model)
對象是強類型的(作為 IEnumerable<Movie>
對象),迴圈中的每一個 item 的類型被類型化為 Movie
。除了其他好處外,這意味著你將獲得代碼的編譯時檢查以及在代碼編輯器里得到完整的智能感知支持:
現在你有了資料庫和用於顯示、編輯、更新以及刪除數據的頁面。在下一篇教程中,我們將學習使用資料庫。