ASP.NET Core MVC 入门教程(第一部分)





5.00/5 (8投票s)
ASP.NET Core MVC 入门
引言
为了最大限度地从这些文章中受益,您应该熟悉 Web 开发的基础知识,理解 HTML、CSS 和 JavaScript 的工作原理,掌握 C# 的基本用法,了解 MVC 模型,并且还应该对 .NET Core、ASP.NET Core 和 Entity Framework Core 的基本概念有所了解。如果您还没有接触过这些,可以从 W3schools 或 Microsoft docs 开始学习。
在这些文章中,我将通过一个名为 BooksStore
的项目,向您展示一个从构思到部署的实际开发过程。我使用了 Windows 10、Visual Studio 2019 和 SQL Server LocalDB。
背景
在我名为 BooksStore
的应用程序中,我将创建一个在线图书目录,客户可以按流派和页码进行浏览;一个购物车,用户可以添加和删除图书;以及一个结账页面,客户可以输入他们的送货详细信息。我还会创建一个管理区域,其中包括用于管理图书目录的创建、读取、更新和删除 (CRUD) 功能,并且我会对其进行保护,以便只有登录的管理员才能进行更改。
Using the Code
创建项目
在 Visual Studio 中,选择 创建新项目,选择 ASP.NET Core Web Application,然后选择 Next(下一步)
将项目命名为 BooksStore
,然后选择 Create(创建)
选择 Web Application (Model-View-Controller),然后选择 Create(创建)
请注意,我选择的是 ASP.NET Core 3.1 – Visual Studio 2019 中的长期支持版本。
修改 Razor 视图
Razor 视图引擎负责处理扩展名为 .cshtml 的视图文件,以生成 HTML 响应。请用以下标记替换 Views/Shared/_Layout.cshtml 文件的内容
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>BooksStore</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>
同时,请用以下标记替换 Views/Home /Index.cshtml 文件的内容
<h3>Welcome to BooksStore</h3>
添加数据模型
由于这是一个电子商务应用程序,最显而易见的模型就是图书。向 Models 文件夹添加一个名为 Book.cs 的类文件,并用以下代码替换该文件的默认内容
using System.ComponentModel.DataAnnotations.Schema;
namespace BooksStore.Models {
public class Book {
public long BookID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
[Column(TypeName = "decimal(8, 2)")]
public decimal Price { get; set; }
public string Genre { get; set; }
}
}
现在,在继续之前,我们可以运行应用程序,以确保它能够按预期进行构建和运行
向应用程序添加数据
安装 Entity Framework Core 包
BooksStore
应用程序将使用 Entity Framework Core (EF Core) 访问 SQL Server LocalDB
数据库来存储其数据。因此,第一步是通过选择 Tools(工具)菜单,然后选择 NuGet Package Manager(NuGet 包管理器)> Package Manager Console (PMC)(包管理器控制台(PMC))来将 EF Core 添加到项目中。在 PMC 中,运行以下命令
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 3.1.1
定义连接字符串
配置设置,例如数据库连接字符串,存储在 JSON 配置文件中。向 appsettings.json 文件添加一个连接字符串
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"BooksStoreConnection": "Server=(localdb)\\MSSQLLocalDB;
Database=BooksStore;MultipleActiveResultSets=true"
}
}
此配置字符串指定了一个名为 BooksStore
的 LocalDB
数据库,并启用了多活动结果集 (MARS) 功能,该功能是 BooksStore
应用程序使用 Entity Framework Core 进行某些数据库查询所必需的。
创建数据库上下文类
Entity Framework Core 通过上下文类提供对数据库的访问。向 Models 文件夹添加一个名为 BooksStoreDbContext.cs 的类文件,并使用以下代码来定义该类
using Microsoft.EntityFrameworkCore;
namespace BooksStore.Models {
public class BooksStoreDbContext: DbContext {
public BooksStoreDbContext (DbContextOptions< BooksStoreDbContext > options)
: base(options) { }
public DbSet<Book> Books { get; set; }
}
}
DbContext
基类提供了对 Entity Framework Core 底层功能的访问,而 Books
属性将提供对数据库中 Book
对象的访问。BooksStoreDbContext
类派生自 DbContext
,并添加了用于读取和写入应用程序数据的属性。
配置 Entity Framework Core
必须配置 Entity Framework Core,以便它知道要连接的数据库类型、描述该连接的连接字符串以及哪个上下文类将呈现数据库中的数据。为此,我们需要更改 Startup.cs 文件中的一些内容
using BooksStore.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
...
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<BooksStoreDbContext>(opts => {
opts.UseSqlServer(
Configuration["ConnectionStrings:BooksStoreConnection"]);
});
}
...
Entity Framework Core 使用 AddDbContext
方法进行配置,该方法注册数据库上下文类并配置与数据库的关系。
UseSQLServer
方法声明正在使用 SQL Server,并且连接字符串通过 IConfiguration
对象读取。
创建存储库
下一步是创建一个存储库接口和实现类。存储库模式是最广泛使用的模式之一,它提供了一种访问数据库上下文类所呈现的功能的一致方法。
向 Models 文件夹添加一个名为 IBooksStoreRepository.cs 的类文件,并使用以下代码来定义接口
using System.Linq;
namespace BooksStore.Models {
public interface IBooksStoreRepository {
IQueryable<Book> Books { get; }
}
}
该接口使用 IQueryable<T>
来允许调用者获取 Book
对象序列。
要创建存储库接口的实现,请在 Models 文件夹中添加一个名为 EFBooksStoreRepository.cs 的类文件,并使用以下代码来定义该类
using System.Linq;
namespace BooksStore.Models {
public class EFBooksStoreRepository : IBooksStoreRepository {
private BooksStoreDbContext context;
public EFBooksStoreRepository (BooksStoreDbContext ctx) {
context = ctx;
}
public IQueryable<Book> Books => context.Books;
}
}
现在,我们将以下语句添加到 Startup
类中,为 IBooksStoreRepository
接口创建一个服务,该服务使用 EFBooksStoreRepository
作为实现类
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<BooksStoreDbContext>(opts => {
opts.UseSqlServer(
Configuration["ConnectionStrings:BooksStoreConnection"]);
});
services.AddScoped<IBooksStoreRepository, EFBooksStoreRepository>();
}
AddScoped
方法创建一个服务,在该服务中,每个 HTTP 请求都会获得自己的存储库对象,这是 Entity Framework Core 通常的使用方式。
创建数据库迁移
Entity Framework Core 能够通过称为迁移的功能,使用数据模型类来生成数据库架构。在 Tools(工具)菜单中,选择 NuGet Package Manager(NuGet 包管理器)> Package Manager Console(包管理器控制台)(PMC)。在 PMC 中,输入以下命令
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 3.1.1
Add-Migration InitialCreate
Update-Database
我们使用了 Add-Migration
命令来创建数据库迁移,并使用 Update-Database
命令将其应用到数据库。我们还从 nuget 安装了 Microsoft.EntityFrameworkCore.Tools
包来使用这些命令。
创建种子数据
为了填充数据库并提供一些示例数据,我在 Models 文件夹中添加了一个名为 SeedData.cs 的类文件,并使用以下代码定义了该类
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace BooksStore.Models
{
public static class SeedData
{
public static void EnsurePopulated(IApplicationBuilder app)
{
BooksStoreDbContext context = app.ApplicationServices.CreateScope().
ServiceProvider.GetRequiredService<BooksStoreDBContext>();
if (context.Database.GetPendingMigrations().Any())
{
context.Database.Migrate();
}
if (!context.Books.Any())
{
context.Books.AddRange(
new Book
{
Title = "Atomic Habits",
Description = "An Easy & Proven Way to Build Good Habits &
Break Bad Ones",
Genre = "Self-Help",
Price = 11.98m
},
new Book
{
Title = "How to Win Friends & Influence People",
Description = "You can go after the job you want...and get it!
You can take the job you have...and improve it!",
Genre = "Self-Help",
Price = 17.46m
},
new Book
{
Title = "Rich Dad Poor Dad",
Description = "What the Rich Teach Their Kids About Money
That the Poor and Middle Class Do Not!",
Genre = "Personal Finance",
Price = 13.41m
},
new Book
{
Title = "The Psychology of Money",
Description = "Doing well with money isn’t necessarily
about what you know. It’s about how you behave.
And behavior is hard to teach,
even to really smart people.",
Genre = "Money Management",
Price = 18.69m
},
new Book
{
Title = "48 Laws of Power",
Description = "Amoral, cunning, ruthless, and instructive,
this piercing work distills 3,000 years of the
history of power into 48 well-explicated laws.",
Genre = "Political Science",
Price = 31.26m
}
);
context.SaveChanges();
}
}
}
}
最后一步是在应用程序启动时填充数据库,我们通过从 Startup
类中添加对 EnsurePopulated
方法的调用来实现,代码如下
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
SeedData.EnsurePopulated(app);
}
显示图书列表
准备 Controller
在 BooksStore/Controllers 文件夹中的 HomeController.cs 文件中准备 Controller,替换默认内容并使用以下代码
using Microsoft.AspNetCore.Mvc;
using BooksStore.Models;
namespace BooksStore.Controllers
{
public class HomeController : Controller
{
private IBooksStoreRepository repository;
public HomeController(IBooksStoreRepository repo)
{
repository = repo;
}
public IActionResult Index() => View(repository.Books);
}
}
这被称为依赖注入,它的方法允许 HomeController
对象通过 IStoreRepository
接口访问应用程序的存储库,而无需知道已配置了哪个实现类。
更新 View
在 SportsStore/Views/Home 文件夹中的 Index.cshtml 文件的内容更新为以下标记
@model IQueryable<Book>
@foreach (var p in Model)
{
<div>
<h3>@p.Title</h3>
@p.Description
@p.Genre
<h4>@p.Price.ToString("c")</h4>
</div>
}
运行应用程序
关注点
从上图可以看出,Index.cshtml 视图在一页上显示数据库中的图书。在下一篇文章中,我将添加分页支持,以便视图在每页显示较少数量的产品,用户可以翻页查看完整的目录。
历史
- 2022年3月9日:初始版本