vscode 開發MVC項目記録
需要:
- Visual Studio Code
- 用于 Visual Studio Code 的 C#(最新版本)
- .NET 6.0 SDK
dotnet new mvc -o MvcMovie 新建MVC項目
code -r MvcMovie 加載csproj項目
dotnet dev-certs https --trust 信任證書
为了在开发环境中使用HTTPS,必须要生成加密证书。.net core提供了一个全局工具dotnet-dev-certs,使用该工具可在本地环境中创建自签名的证书。可以通过下面命令行安装该工具:
dotnet tool install -global dotnet-dev-certs
安装成功后,就可以用他自签名的证书。
-ep标志表示将生成证书导出的存储目录;
-p标志表示生成证书的密码。
可以使用-trust选项来信任生成的证书。
- 启动 Kestrel
- 启动浏览器。
- 导航到
https://localhost:5001。
Kestrel 是一个跨平台的适用于 Kestrel。 Kestrel 是包含在 ASP.NET Core 项目模板中的 Web 服务器,默认处于启用状态。
Kestrel 支持以下方案:
- HTTPS
- HTTP/2(在 macOS? 上除外)
- 用于启用 WebSocket 的不透明升级
- 用于获得 Nginx 高性能的 Unix 套接字
添加 NuGet 包
运行以下 .NET CLI 命令:
.NET CLIdotnet tool uninstall --global dotnet-aspnet-codegenerator
dotnet tool install --global dotnet-aspnet-codegenerator
dotnet tool uninstall --global dotnet-ef
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SQLite
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
上述命令添加:
- EF Core 命令行接口 (CLI) 工具
- aspnet-codegenerator 基架工具。
- EF Core 的设计时工具
- EF Core SQLite 提供程序将 EF Core 包作为依赖项进行安装。
- 基架需要的包:
Microsoft.VisualStudio.Web.CodeGeneration.Design和Microsoft.EntityFrameworkCore.SqlServer。
使用基架工具为电影模型生成 Create、Read、Update 和 Delete (CRUD) 页面。
在项目目录中打开命令窗口。 项目目录是包含 Program.cs 和 .csproj 文件的目录。
在 macOS 和 Linux 上,导出基架工具路径:
控制台export PATH=$HOME/.dotnet/tools:$PATH
运行下面的命令:
.NET CLIdotnet-aspnet-codegenerator controller -name MoviesController -m Movie -dc MvcMovieContext --relativeFolderPath Controllers --useDefaultLayout --referenceScriptLibraries -sqlite
下表详细说明了 ASP.NET Core 代码生成器参数:
| 参数 | 说明 |
|---|---|
| -M | 模型的名称。 |
| -dc | 数据上下文。 |
| --relativeFolderPath | 用于创建文件的相对输出文件夹路径。 |
| --useDefaultLayout|-udl | 应为视图使用默认布局。 |
| --referenceScriptLibraries | 向“编辑”和“创建”页面添加 _ValidationScriptsPartial。 |
| -sqlite | 标记来指定 DbContext 是否应使用 SQLite,而不是 SQL Server。 |
使用 h 开关获取 aspnet-codegenerator controller 命令方面的帮助:
dotnet aspnet-codegenerator controller -h
将 SQLite 用于开发,将 SQL Server 用于生产
Program.cs 中突出显示的以下代码展示了如何在开发中使用 SQLite,以及在生产中使用 SQL Server。
(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("ProductionMvcMovieContext")));
}
">var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
builder.Services.AddDbContext(options =>
options.UseSqlite(builder.Configuration.GetConnectionString("MvcMovieContext")));
}
else
{
builder.Services.AddDbContext(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("ProductionMvcMovieContext")));
}
迁移功能来创建数据库。 迁移是可用于创建和更新数据库以匹配数据模型的一组工具。
如果尚未安装 dotnet ef,请安装它作为全局工具:
dotnet tool install --global dotnet-ef
有关 EF Core 的 CLI 的详细信息,请参阅 .Net CLI 的 EF Core 工具引用。
运行以下 .NET CLI 命令:
.NET CLIdotnet ef migrations add InitialCreate
dotnet ef database update
ef migrations add InitialCreate:生成Migrations/{timestamp}_InitialCreate.cs迁移文件。InitialCreate参数是迁移名称。 可以使用任何名称,但是按照惯例,会选择可说明迁移的名称。 因为这是首次迁移,所以生成的类包含用于创建数据库架构的代码。 数据库架构基于在MvcMovieContext类(位于Data/MvcMovieContext.cs文件中)中指定的模型。ef database update:将数据库更新到上一个命令创建的最新迁移。 此命令在用于创建数据库的Migrations/{time-stamp}_InitialCreate.cs文件中运行Up方法。
检查生成的数据库上下文类和注册
对于 EF Core,使用模型执行数据访问。 模型由实体类和表示数据库会话的上下文对象构成。 上下文对象允许查询并保存数据。 数据库上下文派生自 Microsoft.EntityFrameworkCore.DbContext 并指定要包含在数据模型中的实体。
基架创建 Data/MvcMovieContext.cs 数据库上下文类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions options)
: base(options)
{
}
public DbSet Movie { get; set; }
}
}
前面的代码创建一个 DbSet
依赖项注入
ASP.NET Core 通过依赖关系注入 (DI) 生成。 服务(如数据库上下文)在 Program.cs 中向 DI 注册。 这些服务通过构造函数参数提供给需要它们的组件。
在 Controllers/MoviesController.cs 文件中,构造函数使用依赖关系注入将 MvcMovieContext 数据库上下文注入到控制器中。 数据库上下文将在控制器中的每个 CRUD 方法中使用。
基架在 Program.cs 中生成了以下突出显示的代码:
- Visual Studio
- Visual Studio Code
- Visual Studio for Mac
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext(options =>
options.UseSqlite(builder.Configuration.GetConnectionString("MvcMovieContext")));
ASP.NET Core 配置系统读取“MvcMovieContext”数据库连接字符串。
Visual Studio
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovie.db"
}
}}
进行本地开发时,ASP.NET Core 配置系统在 appsettings.json 文件中读取 ConnectionString 键。
InitialCreate 类
检查 Migrations/{timestamp}_InitialCreate.cs 迁移文件:
new
{
Id = table.Column(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column(type: "datetime2", nullable: false),
Genre = table.Column(type: "nvarchar(max)", nullable: true),
Price = table.Column(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
">using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
在上述代码中:
InitialCreate.Up创建 Movie 表,并将Id配置为主键。InitialCreate.Down还原Up迁移所做的架构更改。
控制器中的依赖项注入
打开 Controllers/MoviesController.cs 文件并检查构造函数:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
构造函数使用依赖关系注入将数据库上下文 (MvcMovieContext) 注入到控制器中。 数据库上下文将在控制器中的每个 CRUD 方法中使用。
测试“创建”页。 输入并提交数据。
测试“编辑”、“详细信息”和“删除”页 。
可以为 null 的类型 (int?)。
Lambda 表达式会被传入 FirstOrDefaultAsync 方法以选择与路由数据或查询字符串值相匹配的电影实体。
C#var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
如果找到了电影,Movie 模型的实例则会被传递到 Details 视图:
return View(movie);
检查 Views/Movies/Details.cshtml 文件的内容:
Details
Movie
-
@Html.DisplayNameFor(model => model.Title)
-
@Html.DisplayFor(model => model.Title)
-
@Html.DisplayNameFor(model => model.ReleaseDate)
-
@Html.DisplayFor(model => model.ReleaseDate)
-
@Html.DisplayNameFor(model => model.Genre)
-
@Html.DisplayFor(model => model.Genre)
-
@Html.DisplayNameFor(model => model.Price)
-
@Html.DisplayFor(model => model.Price)
Edit |
Back to List
">@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Details";
}
<h1>Detailsh1>
<div>
<h4>Movieh4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Title)
dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Title)
dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.ReleaseDate)
dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.ReleaseDate)
dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Genre)
dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Genre)
dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Price)
dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Price)
dd>
dl>
div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit |
Index">Back to Lista>
div>
视图文件顶部的 @model 语句可指定视图期望的对象类型。 创建影片控制器时,将包含以下 @model 语句:
@model MvcMovie.Models.Movie
此 @model 指令允许访问控制器传递给视图的影片。 Model 对象为强类型对象。 例如,在 Details.cshtml 视图中,代码通过强类型的 Model 对象将每个电影字段传递给 DisplayNameFor 和 DisplayFor HTML 帮助程序。 Create 和 Edit 方法以及视图也传递一个 Movie 模型对象。
检查电影控制器中的 Index.cshtml 视图和 Index 方法。 请注意代码在调用 View 方法时是如何创建 List 对象的。 代码将此 Movies 列表从 Index 操作方法传递给视图:
// GET: Movies
public async Task Index()
{
return View(await _context.Movie.ToListAsync());
}
创建电影控制器后,基架将以下 @model 语句包含在 Index.cshtml 文件的顶部:
@model IEnumerable
@model 指令允许使用强类型的 Model 对象访问控制器传递给视图的电影列表。 例如,在 Index.cshtml 视图中,代码使用 foreach 语句通过强类型 Model 对象对电影进行循环遍历:
Index
Create New
@Html.DisplayNameFor(model => model.Title)
@Html.DisplayNameFor(model => model.ReleaseDate)
@Html.DisplayNameFor(model => model.Genre)
@Html.DisplayNameFor(model => model.Price)
@foreach (var item in Model) {
@Html.DisplayFor(modelItem => item.Title)
@Html.DisplayFor(modelItem => item.ReleaseDate)
@Html.DisplayFor(modelItem => item.Genre)
@Html.DisplayFor(modelItem => item.Price)
Edit |
Details |
Delete
}
">@model IEnumerable
@{
ViewData["Title"] = "Index";
}
<h1>Indexh1>
<p>
<a asp-action="Create">Create Newa>
p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
th>
<th>
@Html.DisplayNameFor(model => model.Genre)
th>
<th>
@Html.DisplayNameFor(model => model.Price)
th>
<th>th>
tr>
thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
td>
<td>
@Html.DisplayFor(modelItem => item.Price)
td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit |
Details" asp-route-id="@item.Id">Details |
Delete" asp-route-id="@item.Id">Delete
td>
tr>
}
tbody>
table>
因为 Model 对象为强类型(作为 IEnumerable 对象),因此循环中的每个项都被类型化为 Movie。 编译器还有一些其他优势,比如验证代码中使用的类型。