65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (8投票s)

2022 年 3 月 9 日

CPOL

6分钟阅读

viewsIcon

18631

ASP.NET Core MVC 入门

引言

为了最大限度地从这些文章中受益,您应该熟悉 Web 开发的基础知识,理解 HTML、CSS 和 JavaScript 的工作原理,掌握 C# 的基本用法,了解 MVC 模型,并且还应该对 .NET Core、ASP.NET Core 和 Entity Framework Core 的基本概念有所了解。如果您还没有接触过这些,可以从 W3schoolsMicrosoft 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"
  }
}

此配置字符串指定了一个名为 BooksStoreLocalDB 数据库,并启用了多活动结果集 (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日:初始版本
© . All rights reserved.