Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载

Asp.Net Core 6.0 MVC 入门

    • 简介
    • 目标
    • 第一章 创建Asp.Net Core Web应用
    • 第二章 从Model开始
    • 第三章 Model之后皆基架
    • 第四章 运行应用
    • 第五章 数据搜索
    • 代码下载

简介

此教程在轻松愉快的氛围中介绍一个具有控制器和视图的 ASP.NET Core MVC Web 图书管理应用。
QQ群577922290
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第1张图片

目标

对于初学者而言,在教程结束时,你将拥有一个管理和显示图书数据的简单应用,同时你还将会对自身的编程技术充满信心。

Visual Studio 2022下载安装操作不在本教程范围内,因为操作基本就是选择,然后下一步。如果安装失败,可自行百度!
下载地址:https://visualstudio.microsoft.com/zh-hans/free-developer-offers/

第一章 创建Asp.Net Core Web应用

  • 启动Visual Studio 2022,单击创建新项目(N)
  • 在创建新项目对话框中选择ASP.NET Core Web 应用(模型-视图-控制器) 单击下一步
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第2张图片
  • 在配置新项目对话框中输入”项目名称“为BookQuerySystem可自行命名),自行选择位置(L),单击下一步
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第3张图片
  • 在配置其他信息对话框中,框架(F) 选择”.NET 6.0(长期支持)“、身份验证类型(A) 选”“、勾上配置HTTPS(H) 选择框,单击创建
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第4张图片
    在几秒钟的等待之后Visual Studio 2022 使用默认项目模板为我们创建了一个叫BookQuerySystemMVC项目。 这是一个简单的项目,接下来我们按 Ctrl+F5来运行它。
    Ctrl+F5 是在非调试情况下启动应用,在这情况下我们依然可以更改代码、保存文件和刷新浏览器查看代码更改后的页面效果。

如果项目没有配置使用 SSL,Visual Studio 会弹出对话框:

  • 如果信任 IIS Express SSL 证书,请选择“是”;
  • 如果你同意信任开发证书,请选择“是”;
  • 以上内容看不懂没有关系,目前你只需要选择"是"。
  • 如果项目已配置使用 SSL,则不会弹出对话框。

同时我们也可以从“调试”菜单中以调试或非调试模式启动应用;
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第5张图片
也可以通过选择工具栏中的“BookQuerySystem”按钮来调试应用;
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第6张图片
下图是应用在Microsoft Edge浏览器上的运行效果!
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第7张图片
在Microsoft Edge浏览器中按F12会调用开发者工具,单击左下方红框里的 切换仿真设备按钮 ,浏览器会模仿移动端网页尺寸。当窗口缩小到移动尺寸时,网页内容会智能调整显示位置,网页右上方红框位置会出现下拉框,我们通常称这种网页布局为响应式布局。
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第8张图片

网页响应式布局归功于一个叫做Bootstrap的前端框架,如果你目前不懂什么是Bootstrap也没有关系,在以后的教程中我们会学到相关知识,你现在只要知道Bootstrap懂你就可以了!本教程的宗旨是用通俗易懂的语言让你站在整体的高度上来理解Asp.Net Core Mvc,而不是让你深陷于每一个细节的泥潭中!

也许这是你创建的第一个应用程序,虽然一行代码也没有输入,但还是要恭喜你,你成功了!多一些愉悦,少一些挫败感,快乐的编程!

第二章 从Model开始

上一章我已经创建了程序,但是程序中什么也没有,这并不是我们希望看到的。
图书数据是放在数据库中的,本章我们创建专门用来管理数据库中图书数据的类。这些类就是MVC中的Model部分。
首先创建一个叫Book的模型类,它定义了数据库中图书数据的属性。什么是图书数据的属性?比如说图书的Title、Id、price等都是图书属性。
右键单击 Models 文件夹,单击“添加” -> “类” 。 文件命名为Book.cs
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第9张图片

namespace BookQuerySystem.Models
{
    public class Book
    {
        
        public int Id { get; set; } 
        public string Title { get; set; }
        public string ClassiFication { get; set; }  
        public string Author { get; set; }
        [DataType(DataType.Date)]
        public DateTime PublicationDate { get; set; }
        public decimal price { get; set; }

    }
}

Book 类包含一个 Id ,也是数据的主键。什么是数据的主键?简单理解就是唯一的编号,用来检索
Book还包含这些属性:Title(书名)、ClassiFication(分类)、Author(作者)、PublicationDate(出版日期),Price(价格)。
PublicationDate上的DataType 特性声明了数据的类型 为Date。 那么特性又是什么东西?简单理解这里的特性就是在PublicationDate属性前面加一个 [ ] 方括号,然后把要给PublicationDate声明的信息放在方括号里。
现在我们收到了一个错误提示:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第10张图片
错误 CS0246 未能找到类型或命名空间名“DataTypeAttribute”(是否缺少 using 指令或程序集引用?) BookQuerySystem
解决这个错误的方法很简单,把鼠标放在红线上左键单击显示可能的修补程序。
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第11张图片
左键单击using System.ComponentModel.DataAnnotations;
现在Book类的代码如下:

using System.ComponentModel.DataAnnotations;

namespace BookQuerySystem.Models
{
    public class Book
    {
        
        public int Id { get; set; } 
        public string Title { get; set; }
        public string ClassiFication { get; set; }  
        public string Author { get; set; }
        [DataType(DataType.Date)]
        public DateTime PublicationDate { get; set; }
        public decimal Price { get; set; }

    }
}

到这里,一个清晰明了的Book数据模型创建成功了,你通关了!恭喜你再一次站在了人生的巅峰!

第三章 Model之后皆基架

上一章我们创建了一个Book数据模型类,通常我们称呼这个类为实体类。那么问题来了,这个实体类是做什么用的?你猜对了,当然是用来和数据库中的Book数据相互映射的。
映射:代数里,映射是个术语名词,指两个元素的集之间的元素相互“对应”的关系。
简单理解就是实体Book类和数据中的Book数据是一根绳上的蚂蚱!而Entity Framework Core 就是这根绳。
Entity Framework Core:轻量、可扩展、跨平台、开源的Entity Framework数据访问框架。
我们可以通过Entity Framework Core来连接数据库,并可以用Book实体类来处理数据库中的Book数据以实现底层数据的增、删、改、查。没错,藏在数据库中的数据我们称它为底层数据。

下面我们先安装Entity Framework Core:

  • 添加 NuGet 包
    工具(T)->NuGet 包管理器(N)->包管理器控制台(O)
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第12张图片

  • 左键单击下方程序包管理器控制台,在红框位置PM>后输入命令(建议你粘贴复制下方代码):

Install-Package Microsoft.EntityFrameworkCore.Design

Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第13张图片
3.6164887秒之后,EF Core终于安装完毕。你用了多少秒,可以在下方留言告诉我,看看谁用时最短!
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第14张图片

  • 使用**基架工具(脚手架)**给Book实体类生成 Create、Delete、Update和Read (增、删、改、查) 页面,脚手架一词在百度百科中是这样解释的:脚手架是为了保证各施工过程顺利进行而搭设的工作平台。
  • 在右侧“解决方案资源管理器”中,右键单击“Controllers”文件夹->“添加”>“新建基架项目”。
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第15张图片
  • 在弹出的“添加已搭建基架的新项”对话框中,选择“视图使用Entity Framework”的MVC控制器->“添加” 。
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第16张图片
  • “添加视图使用Entity Framework 的 MVC控制器”对话框中选择如下:
  • 模型类(M)”下拉列表中,选择“Book (BookQuerySystem.models)”。
  • 数据上下文类(D)”行中,选择 +(加号) 。
  • 添加数据上下文”对话框中,将自动生成类名 BookQuerySystem.Data.BookQuerySystemContext,选择添加
  • 视图”和“控制器名称(C)”,保持默认并选择添加

别怕,你电脑没死机!休息,休息一会儿!
事实证明基架就是打工人,我们才是老板!一番等待之后,基架为我们干了很多活:

  • 基架在 BookQuerySystem.csproj 项目文件中插入所需的包引用。(什么?你没找到BookQuerySystem.csproj 项目文件?在解决方案资源管理器中双击BookQuerySystem)(什么?你找不到解决方案资源管理器?好吧!等我给你截个图)
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第17张图片

Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第18张图片

  • 在 Program.cs 文件的依赖注入容器中注册了数据库上下文。
    Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第19张图片

  • 基架将数据库连接字符串添加到 appsettings.json 文件。

我们之前谈过基架的职能,目前只要知道基架更新了什么就可以,至于它是怎么更新的并不重要。

基架还为我们创建了以下内容:

  • BooksController:Controllers/BooksController.cs
    BooksController

“创建(Create)”、“删除(Delete)”、“详细信息(Details)”、“编辑(Edit)”和“索引(Index)”的Razor视图文件:Views/Books/*.cshtml
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第20张图片

数据库上下文类:Data/BookQuerySystemContext.cs)”
Data
目前只要知道基架创建了什么就可以,不要强迫自己把每一个细节搞清楚,要站在全局的高度看问题,细节就先留给基架吧。

实体类的工作已经做完,现在我们使用EF Core的迁移功能来创建数据库。
迁移:是一组创建和更新数据库以匹配实体类的工具。
迁移功能的用法也非常简单:

  • 工具->NuGet 包管理器->程序包包管理器控制台。
    在程序包管理器控制台的PM>后输入代码
Add-Migration InitialCreate

InitialCreate单词的翻译是初始创建,未必非要用这个词,你也可以自行命名。
现在项目中多出了一个Migrations文件夹,里面的{timestamp}_InitialCreate.cs 迁移文件包含了创建书库的代码,timestamp根据时间不同而定,我的就是20211206090830_InitialCreate.cs。
现在用于创建数据库的代码已经存在,我们用Update-Database命令来真正的创建数据库。

  • 在程序包管理器控制台的PM>后输入代码
Update-Database

Update-Database:将数据库更新到上一个最近创建的迁移,我们上一个迁移是20211206090830_InitialCreate.cs,现在数据库和它保持同步了。Update-Database命令本质就是运行了一下20211206090830_InitialCreate.cs中的Up方法,一点都不神秘。

using System;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace BookQuerySystem.Migrations
{
    public partial class InitialCreate : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Book",
                columns: table => new
                {
                    Id = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    Title = table.Column<string>(type: "nvarchar(max)", nullable: false),
                    ClassiFication = table.Column<string>(type: "nvarchar(max)", nullable: false),
                    Author = table.Column<string>(type: "nvarchar(max)", nullable: false),
                    PublicationDate = table.Column<DateTime>(type: "datetime2", nullable: false),
                    Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Book", x => x.Id);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Book");
        }
    }
}

凭借阅读英文,大家也能猜出Up方法大概都做了什么。这个也不重要,我们知道有这么一回事就行了,不用深究。

第四章 运行应用

小伙伴们,下面是见证奇迹的时刻,让我们把应用运行起来吧!老规矩,按Ctrl+F5非调试情况下启动应用。
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第21张图片
惊不惊喜?意不意外?(可以留言告诉我!)
第一章啥样,现在还啥样!网页一点变化也没有。为什么会这样?
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第22张图片

一个 HTTP 终点是 Web 应用程序中的Url目标,如 https://localhost:7260/Books ,Books就是目标。
https://localhost:{PORT}/Books ,将 {PORT} 替换为你自己的端口号。看不明白就在刚才你打开的网页网址后加上/Books就行了。
打开https://localhost:7260/Books后才会看我们的劳动成果!
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第23张图片

现在我们试试创建图书功能,左键单击网页中的Create New。在创建页面填写书籍信息后点击Create提交创建信息:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第24张图片
现在Books页面显示了新添加书籍的信息。
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第25张图片
在Price(Price)26.6之后,我们看到了Edit(编辑)、Detail(查看详情)和Delete(删除)选项,请自行测试一遍。
一本书看起来很孤独,我们再自行添加几本书。
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第26张图片
页面现在看起来顺眼多了,但是如何才能把英语换成汉语那?
打开Models文件夹下的Books.cs实体类:
在除了Id属性之外的属性上添加[Display(Name=" 中文")],我们之前讲过,这种写法叫做给属性添加特性。

using System.ComponentModel.DataAnnotations;

namespace BookQuerySystem.Models
{
    public class Book
    {
        
        public int Id { get; set; } 
        
        [Display(Name ="书名")]
        public string Title { get; set; }
        
        [Display(Name ="类型")]
        public string ClassiFication { get; set; } 
         
        [Display(Name ="作者")]
        public string Author { get; set; }
        
        [Display(Name ="首版日期")]
        [DataType(DataType.Date)]
        public DateTime PublicationDate { get; set; }
        
        [Display(Name ="价格")]
        public decimal Price { get; set; }

    }
}

重新启动应用:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第27张图片
添加特性的Book实体类各个属性都以中文方式显示在了页面上。从字面上我们也能理解Display是显示的意思。[Display(Name=" “)]就是把他修饰的元素名显示为” “里的内容,比如说[Display(Name=” 价格")]。
把Edit、Details、Delete也改成汉语:
打开Views/Books/Index.cshtml文件

@model IEnumerable<BookQuerySystem.Models.Book>

@{
    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.ClassiFication)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Author)
            th>
            <th>
                @Html.DisplayNameFor(model => model.PublicationDate)
            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.ClassiFication)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.PublicationDate)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edita> |
                <a asp-action="Details" asp-route-id="@item.Id">Detailsa> |
                <a asp-action="Delete" asp-route-id="@item.Id">Deletea>
            td>
        tr>
}
    tbody>
table>

Index.cshtml最后几行找到代码
在这里插入图片描述
修改如下:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第28张图片
左键点击热重载:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第29张图片
刷新浏览器:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第30张图片
还是Views/Books/Index.cshtm文件,在上面找到
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第31张图片
修改代码:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第32张图片
热重载:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第33张图片
修改之后网页终于大部分显示的都是汉语了,不过细心的小伙伴会发现页面中竟然还有英语。之前修改的是Views/Books/Index.cshtm文件中的内容,在Program.cs文件中路由格式如下:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

这是一种路由格式,controller就是控制器,action指明控制器中的方法,在本例中id就是图书Id编号。id后面加一个?号表示这个id可空,可空就是在路由过程中可以写,也可以省略。
https://localhost:7260/Books是一个Url,也就是网址,当访问这个网址时,我们实际访问的是https://localhost:7260/Books/Index页面,Books是控制器,Index是Books控制器中的方法,/Books=/Books/Index就是Program.cs文件中路由定义好的默认规则。如果直接启动应用,Url将默认是https://localhost:7260/ , /=/Home/Index 是默认路由。(以上路由知识如果没看懂则可以直接无视,这并不影响应用运行)
打开Views/Shared/_layout.cshtml文件,代码修改如下:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - 图书查询系统title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/BookQuerySystem.styles.css" asp-append-version="true" />
head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">图书查询系统a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon">span>
                button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">首页a>
                        li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Books" asp-action="Index">图书列表a>
                        li>
                    ul>
                div>
            div>
        nav>
    header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        main>
    div>

    <footer class="border-top footer text-muted">
        <div class="container">
            © 2021 - 图书查询系统 - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacya>
        div>
    footer>
    <script src="~/lib/jquery/dist/jquery.min.js">script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js">script>
    <script src="~/js/site.js" asp-append-version="true">script>
    @await RenderSectionAsync("Scripts", required: false)
body>
html>


这是布局页面,把其它网页中重复出现的共用内容写在布局页里。日后维护时修改共用内容只需修改这一页即可!其他页面内容都在@RenderBody()位置呈现,除此之外都是各页面的共用内容。依照下图修改红框中内容:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第34张图片
热重载:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第35张图片
修改Views/Books/Create.cshtml文件:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第36张图片
修改后代码:

@model BookQuerySystem.Models.Book

@{
    ViewData["Title"] = "录入图书";
}

<h1>图书录入h1>

<h4>图书h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger">div>
            <div class="form-group">
                <label asp-for="Title" class="control-label">label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="ClassiFication" class="control-label">label>
                <input asp-for="ClassiFication" class="form-control" />
                <span asp-validation-for="ClassiFication" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="Author" class="control-label">label>
                <input asp-for="Author" class="form-control" />
                <span asp-validation-for="Author" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="PublicationDate" class="control-label">label>
                <input asp-for="PublicationDate" class="form-control" />
                <span asp-validation-for="PublicationDate" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="Price" class="control-label">label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger">span>
            div>
            <div class="form-group">
                <input type="submit" value="创建" class="btn btn-primary" />
            div>
        form>
    div>
div>

<div>
    <a asp-action="Index">返回图书列表a>
div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Views/Books/Delete.cshtml文件修改后代码:

@model BookQuerySystem.Models.Book

@{
    ViewData["Title"] = "删除";
}

<h1>删除h1>

<h3>你确定要删除这本书?h3>
<div>
    <h4>图书h4>
    <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.ClassiFication)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.ClassiFication)
        dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Author)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Author)
        dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.PublicationDate)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.PublicationDate)
        dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Price)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Price)
        dd>
    dl>
    
    <form asp-action="Delete">
        <input type="hidden" asp-for="Id" />
        <input type="submit" value="删除" class="btn btn-danger" /> |
        <a asp-action="Index">返回a>
    form>
div>

Views/Books/Details.cshtml文件修改后代码:

@model BookQuerySystem.Models.Book

@{
    ViewData["Title"] = "详情";
}

<h1>详情h1>

<div>
    <h4>图书h4>
    <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.ClassiFication)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.ClassiFication)
        dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Author)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Author)
        dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.PublicationDate)
        dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.PublicationDate)
        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">编辑a> |
    <a asp-action="Index">返回a>
div>

Views/Books/Edit.cshtml文件修改后代码:

@model BookQuerySystem.Models.Book

@{
    ViewData["Title"] = "编辑";
}

<h1>编辑h1>

<h4>图书h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger">div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="Title" class="control-label">label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="ClassiFication" class="control-label">label>
                <input asp-for="ClassiFication" class="form-control" />
                <span asp-validation-for="ClassiFication" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="Author" class="control-label">label>
                <input asp-for="Author" class="form-control" />
                <span asp-validation-for="Author" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="PublicationDate" class="control-label">label>
                <input asp-for="PublicationDate" class="form-control" />
                <span asp-validation-for="PublicationDate" class="text-danger">span>
            div>
            <div class="form-group">
                <label asp-for="Price" class="control-label">label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger">span>
            div>
            <div class="form-group">
                <input type="submit" value="保存" class="btn btn-primary" />
            div>
        form>
    div>
div>

<div>
    <a asp-action="Index">返回a>
div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

现在我们修改欢迎页面Views/Home/Index.cshtml :

@{
    ViewData["Title"] = "主页";
}

<div class="text-center">
    <h1 class="display-4">你好!h1>
    <p> <a href="https://blog.csdn.net/baidu_38495508/article/details/121731637">欢迎学习图书查询系统教程a>p>
div>

第五章 数据搜索

试想一下,如果数据库中存储着一万本书,你要找到其中一本书的数据,一条一条的翻找信息既费时又费力。既然是图书查询系统,那么应该有查询功能。

  • 更新Controllers/BooksController.cs 中的 Index 方法,代码如下:
 public async Task<IActionResult> Index(string search)
        {
            var books = from b in _context.Book
                        select b;
            if (!string.IsNullOrEmpty(search))
            {
                books = books.Where(s=>s.Title!.Contains(search));
            }
            return View(await books.ToListAsync());
        }
  • 更新Views/Books/Index.cshtml文件代码如下:
@model IEnumerable<BookQuerySystem.Models.Book>

@{
    ViewData["Title"] = "图书列表";
}

<h1>图书列表h1>

<p>
    <a asp-action="Create">录入图书a>
p>


<form asp-controller="Books" asp-action="Index">
    <p>
        书名: <input type="text" name="search" />
        <input type="submit" value="搜索" />
    p>
form>


<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            th>
            <th>
                @Html.DisplayNameFor(model => model.ClassiFication)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Author)
            th>
            <th>
                @Html.DisplayNameFor(model => model.PublicationDate)
            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.ClassiFication)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.PublicationDate)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">编辑a> |
                <a asp-action="Details" asp-route-id="@item.Id">详情a> |
                <a asp-action="Delete" asp-route-id="@item.Id">删除a>
            td>
        tr>
}
    tbody>
table>

热重载:
在搜索框中输入“老人”。Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第37张图片
左键单击“搜索”。
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第38张图片
系统通过输入内容为我们搜索并匹配到了老人与海这本书。如果我们想通过书的类型搜索数据又应该怎么做那?

右键单击解决方案资源管理器中的BookQuerySystem->添加->新建文件夹,文件夹命名为ViewModels。
创建新类文件ViewModels/BookClassiFicationViewModel.cs ,类名有点长!好在易懂。


namespace BookQuerySystem.ViewModels
{
    public class BookClassiFicationViewModel
    {
        public List<Book>? Books { get; set; }
        public SelectList? ClassiFications { get; set; }
        public string? BookClassiFication { get; set; }
        public string? Search { get; set; }
    }
}

  • 更新Controllers/BooksController.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using BookQuerySystem.Data;
using BookQuerySystem.Models;
using BookQuerySystem.ViewModels;

namespace BookQuerySystem.Controllers
{
    public class BooksController : Controller
    {
        private readonly BookQuerySystemContext _context;

        public BooksController(BookQuerySystemContext context)
        {
            _context = context;
        }

        // GET: Books
        public async Task<IActionResult> Index(string bookClassiFication , string search)
        {
            IQueryable<string> classiFicationQuery = from c in _context.Book
                                                     orderby c.ClassiFication
                                                     select c.ClassiFication;
            var books = from b in _context.Book
                        select b;
            if (!string.IsNullOrEmpty(search))
            {
                books = books.Where(s=>s.Title!.Contains(search));
            }

            if (!string.IsNullOrEmpty(bookClassiFication))
            {
                books = books.Where(b=>b.ClassiFication==bookClassiFication);
            }

            var bookClassiFicationVM = new BookClassiFicationViewModel
            {
                ClassiFications = new SelectList(await classiFicationQuery.Distinct().ToListAsync()),
                Books = await books.ToListAsync()
            };

            return View(bookClassiFicationVM);
        }

        // GET: Books/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var book = await _context.Book
                .FirstOrDefaultAsync(m => m.Id == id);
            if (book == null)
            {
                return NotFound();
            }

            return View(book);
        }

        // GET: Books/Create
        public IActionResult Create()
        {
            return View();
        }

        // POST: Books/Create
        // To protect from overposting attacks, enable the specific properties you want to bind to.
        // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,Title,ClassiFication,Author,PublicationDate,Price")] Book book)
        {
            if (ModelState.IsValid)
            {
                _context.Add(book);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(book);
        }

        // GET: Books/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var book = await _context.Book.FindAsync(id);
            if (book == null)
            {
                return NotFound();
            }
            return View(book);
        }

        // POST: Books/Edit/5
        // To protect from overposting attacks, enable the specific properties you want to bind to.
        // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ClassiFication,Author,PublicationDate,Price")] Book book)
        {
            if (id != book.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(book);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!BookExists(book.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(book);
        }

        // GET: Books/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var book = await _context.Book
                .FirstOrDefaultAsync(m => m.Id == id);
            if (book == null)
            {
                return NotFound();
            }

            return View(book);
        }

        // POST: Books/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var book = await _context.Book.FindAsync(id);
            _context.Book.Remove(book);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        private bool BookExists(int id)
        {
            return _context.Book.Any(e => e.Id == id);
        }
    }
}

  • 更新Views/Books/Index.cshtml文件代码如下:
@model BookQuerySystem.ViewModels.BookClassiFicationViewModel

@{
    ViewData["Title"] = "图书列表";
}

<h1>图书列表h1>

<p>
    <a asp-action="Create">录入图书a>
p>


<form asp-controller="Books" asp-action="Index" method="get">
    <p>
        <select asp-for="BookClassiFication" asp-items="Model.ClassiFications">
            <option value="">所有类别option>
        select>

        书名: <input type="text" name="Search" />
        <input type="submit" value="搜索" />
    p>
form>


<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Books[0].Title)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Books[0].ClassiFication)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Books[0].Author)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Books[0].PublicationDate)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Books[0].Price)
            th>
            <th>th>
        tr>
    thead>
    <tbody>
@foreach (var item in Model.Books) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.ClassiFication)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.PublicationDate)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">编辑a> |
                <a asp-action="Details" asp-route-id="@item.Id">详情a> |
                <a asp-action="Delete" asp-route-id="@item.Id">删除a>
            td>
        tr>
}
    tbody>
table>

热重载:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第39张图片
入门教程到这里就结束了,编程是不是很简单,很快乐?

代码下载

教程最后还会提供加上会员管理系统的代码码,使项目功能完整。小伙伴们可以下载源码自行修改。

  • 预览下加入会员管理系统的应用效果::

Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第40张图片
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第41张图片
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第42张图片
效果还行 ,在没有注册登录之前只可以浏览注册和登录页面,现在非用户已经无法看到你书库的图书信息了。
角色已经添加完毕,效果如下:
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第43张图片
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第44张图片
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第45张图片
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第46张图片
Asp.Net Core 6.0 Mvc入门 图书查询系统 附带源码下载_第47张图片
小伙伴们可以下载代码自行阅读,修改,使用。

代码在 QQ群577922290 群文件中共享。

你可能感兴趣的:(.NET,Asp.Net,Core,6.0,mvc,asp.net,前端)