ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(五)外借/阅览图书信息的增删改查
前言:
本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作。
本系列文章主要参考资料:
微软文档:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windows
《Pro ASP.NET MVC 5》、《锋利的 jQuery》
此系列皆使用 VS2017+C# 作为开发环境。如果有什么问题或者意见欢迎在留言区进行留言。
项目 github 地址:https://github.com/NanaseRuri/LibraryDemo
本章内容:通过模态窗口确认是否提交表单、select 元素、表单提交数组、checkbox、关闭窗口前确认、EF 修改主键
一、外借/阅览图书信息首页
这里的实现和上一章大致一致,但这里我打算通过前面的 BookDetail 页面进入到这个页面:
首先创建一个视图模型同时保存 BookDetail 的信息并传递 IEnumerable<Book> 以便对对应 BookDetails 的外借/阅览图书信息进行展示:
public class BookListViewModel
{
public IEnumerable<BookDetails> BookDetails { get; set; }
public PagingInfo PagingInfo { get; set; }
}
对应 BookDetail 的外借/阅览图书信息首页:
[Authorize(Roles = "Admin")]
public IActionResult Books(string isbn)
{
BookEditModel model = new BookEditModel()
{
Books = _lendingInfoDbContext.Books.Include(b => b.Keeper).AsNoTracking().Where(b => b.ISBN == isbn),
BookDetails = _lendingInfoDbContext.BooksDetail.AsNoTracking().FirstOrDefault(b => b.ISBN == isbn)
};
if (model.BookDetails == null)
{
TempData["message"] = "未找到目标书籍";
return RedirectToAction("BookDetails");
}
return View(model);
}
视图:
@using LibraryDemo.Models.DomainModels
@model BookEditModel @{
ViewData["Title"] = "外借/阅览书籍信息";
Book temp = new Book();
} <script>
function confirmDelete() {
var barcodes = document.getElementsByName("barcodes");
var message="确认删除";
for (i in barcodes) {
if (barcodes[i].checked) {
var book = barcodes[i].parentElement.nextElementSibling.firstElementChild.innerHTML;
message=message+"《"+book+"》";
}
}
message = message + "?";
if (confirm(message) == true) {
return true;
} else {
return false;
}
}
</script> <style type="text/css">
tr + tr {
border-top: thin solid gray;
} td + td {
padding-left: 50px;
} .container {
width: 1200px;
}
</style> <h2>《@Model.BookDetails.Name》</h2>
<br /> @if (TempData["message"] != null)
{
<p style="font-size: large;color:red" >@TempData["message"]</p>
<br />
<br />
} <form asp-action="RemoveBooks" method="post">
<div>
<a class="btn btn-primary" asp-action="AddBook" asp-route-isbn="@Model.BookDetails.ISBN">添加外借书籍</a>
<button type="submit" class="btn btn-danger" onclick="return confirmDelete()"> 删除外借书籍</button>
</div>
<br />
<input type="hidden" name="isbn" value="@Model.BookDetails.ISBN"/>
<table>
<tbody>
<tr>
<td></td>
<td>@Html.LabelFor(b => temp.BarCode)</td>
<td>@Html.LabelFor(b => temp.Bookshelf)</td>
<td>@Html.LabelFor(b => temp.BorrowTime)</td>
<td>@Html.LabelFor(b => temp.MatureTime)</td>
<td>@Html.LabelFor(b => temp.AppointedLatestTime)</td>
<td>@Html.LabelFor(b => temp.State)</td>
<td>@Html.LabelFor(b => temp.KeeperId)</td>
<td>编辑借出信息</td>
</tr>
@if (Model.Books.ToList().Count == )
{
<tr><td colspan="">未有《@Model.BookDetails.Name》的外借/阅览书籍信息</td></tr>
}
@foreach (var book in Model.Books)
{
<tr>
<td><input type="checkbox" name="barcodes" value="@book.BarCode"/></td>
<td><a asp-action="EditBook" asp-route-barcode="@book.BarCode">@Html.DisplayFor(b => book.BarCode)</a></td>
<td>@Html.DisplayFor(b => book.BookshelfId)</td>
<td>@Html.DisplayFor(b => book.BorrowTime)</td>
<td>@Html.DisplayFor(b => book.MatureTime)</td>
<td>@Html.DisplayFor(b => book.AppointedLatestTime)</td>
<td>@Html.DisplayFor(b => book.State)</td>
<td>@Html.DisplayFor(b => book.Keeper.Name)</td>
<td><a asp-action="EditLendingInfo" asp-route-barcode="@book.BarCode">编辑</a></td>
</tr>
}
</tbody>
</table>
</form>
结果:



二、添加外借/阅览图书信息
在 21 行中使用了 Bind 特性,使在模型绑定过程中只绑定对应属性名的属性,防止了与其他数据的绑定。 Bind 特性中的属性名区分大小写,与表单中的 input 的 name 一一对应。
26 行使用 .AsNoTracking 告诉 EF 在查询时禁用更改跟踪提高性能,对不需要进行更改的数据的查询都可以带有该方法。
32 行对表单上传的数据进行检验以确认来自同一本书。
34 行中使用 Include 方法告诉 EF 使返回的书架包含架上书本的信息,使 bookshelf.Books 返回一个 ICollection 实例而不是空 ICollection 以将新的外借/阅览图书信息添加其中。
[Authorize(Roles = "Admin")]
public IActionResult AddBook(string isbn)
{
BookDetails bookDetails = _lendingInfoDbContext.BooksDetail.FirstOrDefault(b => b.ISBN == isbn);
if (bookDetails == null)
{
return RedirectToAction("BookDetails", new { isbn = isbn });
}
Book book = new Book()
{
ISBN = bookDetails.ISBN,
Name = bookDetails.Name,
FetchBookNumber = bookDetails.FetchBookNumber
};
return View(book);
} [HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> AddBook([Bind("ISBN,Name,FetchBookNumber,BarCode,BookshelfId,State")]Book book)
{
if (ModelState.IsValid)
{
BookDetails bookDetails = _lendingInfoDbContext.BooksDetail.FirstOrDefault(b => b.ISBN == book.ISBN);
Book existBook = _lendingInfoDbContext.Books.AsNoTracking().FirstOrDefault(b => b.BarCode == book.BarCode);
if (existBook != null)
{
TempData["message"] = $"已有二维码为{book.BarCode}的书籍《{existBook.Name}》";
return RedirectToAction("AddBook", new { isbn = book.ISBN });
}
if (bookDetails.Name == book.Name)
{
Bookshelf bookshelf = _lendingInfoDbContext.Bookshelves.Include(b => b.Books).FirstOrDefault(b => b.BookshelfId == book.BookshelfId);
if (bookshelf != null)
{
book.Sort = bookshelf.Sort;
book.Location = bookshelf.Location;
bookshelf.Books.Add(book);
bookshelf.MaxFetchNumber = bookshelf.Books.Max(b => b.FetchBookNumber);
bookshelf.MinFetchNumber = bookshelf.Books.Min(b => b.FetchBookNumber);
}
await _lendingInfoDbContext.Books.AddAsync(book);
await _lendingInfoDbContext.SaveChangesAsync();
TempData["message"] = $"《{book.Name}》 {book.BarCode} 添加成功";
return RedirectToAction("Books", new { isbn = book.ISBN });
}
}
return View(book);
}
视图:
@using LibraryDemo.Models.DomainModels
@model LibraryDemo.Models.DomainModels.Book @{
ViewData["Title"] = "AddBook";
} <script>
window.onload = function () {
$("input").addClass("form-control");
}
window.onbeforeunload = function () {
return "您的数据未保存,确定退出?";
}
function removeOnbeforeunload() {
window.onbeforeunload = "";
}
</script> <h2>@($"为《{Model.Name}》添加借阅/阅览书籍信息")</h2>
<br />
<br />
@if (TempData["message"] != null)
{
<p class="text-success">@TempData["message"]</p>
<br />
<br />
} @Html.ValidationSummary(false, "", new { @class = "text-danger" })
<form asp-action="AddBook" method="post">
<div class="form-group">
@Html.LabelFor(b => b.ISBN)
<input type="text" value="@Model.ISBN" readonly="readonly" name="@nameof(Model.ISBN)" />
</div>
<div class="form-group">
@Html.LabelFor(b => b.Name)
<input type="text" value="@Model.Name" readonly="readonly" name="@nameof(Model.Name)" />
</div>
<div class="form-group">
@Html.LabelFor(b => b.FetchBookNumber)
<input type="text" value="@Model.FetchBookNumber" readonly="readonly" name="@nameof(Model.FetchBookNumber)" />
</div>
<div class="form-group">
@Html.LabelFor(b => Model.BarCode)
@Html.EditorFor(b => Model.BarCode)
</div>
<div class="form-group">
@Html.LabelFor(b => Model.BookshelfId)
@Html.EditorFor(b => Model.BookshelfId)
</div>
<div class="form-group">
@Html.LabelFor(b => Model.State)
@Html.DropDownListFor(b=>Model.State,Enum.GetValues(typeof(BookState)).Cast<Enum>().Select(state =>
{
string enumVal = Enum.GetName(typeof(BookState), state);
string displayVal;
switch (enumVal)
{
case "Normal":
displayVal = "可借阅";
break;
case "Readonly":
displayVal = "馆内阅览";
break;
case "Borrowed":
displayVal = "已借出";
break;
case "ReBorrowed":
displayVal = "被续借";
break;
case "Appointed":
displayVal = "被预约";
break;
default:
displayVal = "";
break;
}
return new SelectListItem()
{
Text=displayVal,
Value = enumVal
};
}))
</div>
<div class="form-group"></div>
<input type="submit" class="btn-success" onclick="removeOnbeforeunload()" />
</form>
三、移除外借/阅览图书信息
此处实现与之前移除书籍信息大致一致,但额外接受一个 isbn 参数用来返回原 isbn 的外借/阅览图书信息首页:
[Authorize(Roles = "Admin")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveBooks(IEnumerable<string> barcodes, string isbn)
{
StringBuilder sb = new StringBuilder();
foreach (var barcode in barcodes)
{
Book book = _lendingInfoDbContext.Books.First(b => b.BarCode == barcode);
_lendingInfoDbContext.Books.Remove(book);
sb.AppendLine($"{book.BarCode} 移除成功");
}
await _lendingInfoDbContext.SaveChangesAsync();
TempData["message"] = sb.ToString();
return RedirectToAction("Books", new { isbn = isbn });
}
四、增删总结果:







五、编辑借阅/阅览书籍信息:
在此设置 BarCode 可以被修改,由于修改主键时会导致 EF 的映射失败,因此EF 不支持直接修改主键,但是可以先将原数据删除再进行添加变相修改主键。
POST 的方法中额外接受一个 BarCode 用来保留原书籍信息。
[Authorize(Roles = "Admin")]
public IActionResult EditBook(string barcode)
{
Book book = _lendingInfoDbContext.Books.FirstOrDefault(b => b.BarCode == barcode);
if (book == null)
{
return RedirectToAction("BookDetails");
}
return View(book);
} [HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditBook(string oldBarCode, [Bind("BarCode,BookshelfId,Name,State")]Book book)
{
if (ModelState.IsValid)
{
Book oldBook = _lendingInfoDbContext.Books.FirstOrDefault(b => b.BarCode == oldBarCode);
if (oldBook == null)
{
TempData["message"] = $"不存在二维码为{oldBarCode}的书籍";
return RedirectToAction("BookDetails");
} if (oldBook.Name == book.Name)
{
book.ISBN = oldBook.ISBN;
book.FetchBookNumber = oldBook.FetchBookNumber;
Bookshelf bookshelf = _lendingInfoDbContext.Bookshelves.Include(b => b.Books).FirstOrDefault(b => b.BookshelfId == book.BookshelfId);
if (bookshelf != null)
{
book.Sort = bookshelf.Sort;
book.Location = bookshelf.Location;
bookshelf.Books.Remove(oldBook);
bookshelf.Books.Add(book);
} _lendingInfoDbContext.Books.Remove(oldBook);
_lendingInfoDbContext.Books.Add(book);
await _lendingInfoDbContext.SaveChangesAsync();
TempData["message"] = "修改成功";
return RedirectToAction("Books", new { isbn = oldBook.ISBN });
}
}
return View(book);
}
@using LibraryDemo.Models.DomainModels
@model LibraryDemo.Models.DomainModels.Book @{
ViewData["Title"] = "EditBook";
} <script>
window.onload = function () {
$("input").addClass("form-control");
}
window.onbeforeunload = function (event) {
return "您的数据未保存,确定退出?";
}
function removeOnbeforeunload() {
window.onbeforeunload = "";
}
</script> <h2>编辑外借书籍</h2>
<br />
<h3>《@Model.Name》</h3>
<br />
<h4>原二维码:@Model.BarCode</h4>
<br />
@Html.ValidationSummary(false,"",new{@class="text-danger"}) <form asp-action="EditBook" method="post">
<input type="hidden" name="oldBarCode" value="@Model.BarCode" />
<input type="hidden" name="Name" value="@Model.Name" />
<div class="form-group">
@Html.LabelFor(b => b.BarCode)
@Html.EditorFor(b => b.BarCode)
</div>
<div class="form-group">
@Html.LabelFor(b => b.BookshelfId)
@Html.EditorFor(b => b.BookshelfId)
</div>
<div class="form-group">
@Html.LabelFor(b => b.State)
@Html.DropDownListFor(b => b.State, Enum.GetValues(typeof(BookState)).Cast<Enum>().Select(state =>
{
string enumVal = Enum.GetName(typeof(BookState), state);
string displayVal;
switch (enumVal)
{
case "Normal":
displayVal = "可借阅";
break;
case "Readonly":
displayVal = "馆内阅览";
break;
case "Borrowed":
displayVal = "已借出";
break;
case "ReBorrowed":
displayVal = "被续借";
break;
case "Appointed":
displayVal = "被预约";
break;
default:
displayVal = "";
break;
}
return new SelectListItem()
{
Text = displayVal,
Value = enumVal,
Selected = Model.State.ToString() == enumVal
};
}))
</div>
<div class="form-group"></div>
<input type="submit" class="btn-success" onclick="removeOnbeforeunload()" />
</form>



TX]GT)63C1L5$4Y]V%7B06.jpg)
ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(五)外借/阅览图书信息的增删改查的更多相关文章
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(四)图书信息的增删改查
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(七) 学生信息增删
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(一) 基本模型以及数据库的建立
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(二)数据库初始化、基本登录页面以及授权逻辑的建立
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(六)学生借阅/预约/查询书籍事务
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(三)密码修改以及密码重置
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/as ...
- 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】
Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...
- 在ASP.NET Core MVC中构建简单 Web Api
Getting Started 在 ASP.NET Core MVC 框架中,ASP.NET 团队为我们提供了一整套的用于构建一个 Web 中的各种部分所需的套件,那么有些时候我们只需要做一个简单的 ...
- 如何搭建一个WEB服务器项目(二)—— 对数据库表进行基本的增删改查操作
使用HibernateTemplate进行增删改查操作 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出 ...
随机推荐
- SeaJS项目完整实例【转】
index.html——主页面. sea.js——SeaJS脚本. init.js——init模块,入口模块,依赖data.jquery.style三个模块.由主页面载入. data.js——data ...
- 胜利大逃亡--hdu --1253(bfs)
Problem Description Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C ...
- CommonTabLayout+ViewPager快速完成APP首页搭建
款APP开始的时候往往少不了多页面的切换,这就涉及到viewpager的使用,以前往往用Google自带的效果去实现,比较麻烦不说,后面做出来的效果还不如人意. 下面就利用CommonTabLayou ...
- IOS开发 APP提交程序上传流程
由于苹果的机制,在非越狱机器上安装应用必须通过官方的App Store,开发者开发好应用后上传App Store,也需要通过审核等环节.AppCan作为一个跨主流平台的一个开发平台,也对ipa包上传A ...
- 【stl学习笔记】list
list使用双向链表来管理元素. 与vector.deque的区别: 1.list不支持随机存取,在list中随机遍历任意元素,是很缓慢的行为 2.任何位置上执行元素的安插和移除都非常快,始终是常数时 ...
- 使用MySQL Workbench进行数据库设计——MySQL Workbench用法总结
转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/48318877 本文出自[我是干勾鱼的博客] 1 简单介绍 MySQL Workb ...
- Deepin-安装php
点击即可:下载:PHP5.6 下载完后执行下面这条shell命令即可完成安装 文件保存为:php_install.sh ,运行时:sh php_install.sh .tar.bz2 cd php- ...
- js中字符串的拼接的另一种方法
// 按一定长度截断字符串,并使用 + 运算符进行连接. // 分隔字符串尽量按语义进行,如不要在一个完整的名词中间断开. // 特别的,对于HTML片段的拼接,通过缩进,保持和HTML相同的结构. ...
- python 【第三篇】函数基础
深浅拷贝 set是一个无序且不重复的元素集合访问速度快天生解决重复问题 #!/usr/bin/env python3 # -*- coding:utf-8 -*- #深浅拷贝 import copy ...
- 可以声明接口,但不可以new接口
接口是一种特殊的抽象类,它包含常量和方法的声明,但没有方法的实现:可以把接口看成是一种特殊的抽象类: 接口实质上是一种规范,它关心的是"做什么",不关心"怎样做" ...