前言:

本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作。

本系列文章主要参考资料:

微软文档: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>

ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(五)外借/阅览图书信息的增删改查的更多相关文章

  1. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(四)图书信息的增删改查

    前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...

  2. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(七) 学生信息增删

    前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...

  3. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(一) 基本模型以及数据库的建立

    前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...

  4. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(二)数据库初始化、基本登录页面以及授权逻辑的建立

    前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...

  5. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(六)学生借阅/预约/查询书籍事务

    前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...

  6. ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(三)密码修改以及密码重置

     前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/as ...

  7. 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 创 ...

  8. 在ASP.NET Core MVC中构建简单 Web Api

    Getting Started 在 ASP.NET Core MVC 框架中,ASP.NET 团队为我们提供了一整套的用于构建一个 Web 中的各种部分所需的套件,那么有些时候我们只需要做一个简单的 ...

  9. 如何搭建一个WEB服务器项目(二)—— 对数据库表进行基本的增删改查操作

    使用HibernateTemplate进行增删改查操作 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出 ...

随机推荐

  1. BZOJ1710: [Usaco2007 Open]Cheappal 廉价回文

    len<=2000的字符串上,给出删掉和添加每种字符的花费,求把字符串变成回文串的最小花费. 首先每个字符添加和删除是一样的,因此花费在添加和删掉每个字符的花费中取小的. 如果每个字符的花费都是 ...

  2. 关于Linux内核学习的一点点总结

    关于Linux内核学习的一点点总结 关键词:Linux, 操作系统,内核 博客列表 由反汇编C程序来理解计算机是如何工作的 通过分析一个简化版时间片轮转多道程序内核代码来认识操作系统中的进程调度 通过 ...

  3. Python()- 面向对象三大特性----继承

    继承: 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类(基类或超类),新建的类是所继承的类的(派生类或子类) 人类和狗 有相同的属性, 提取了一个__init__方法,在这 ...

  4. 没啥用,更换注册表信息使webbrower选择适合的版本

    /// <summary>            /// 修改注册表信息来兼容当前程序            ///             /// </summary>   ...

  5. 基于unicorn-engine的虚拟机的实现(WxSpectre)

    反病毒虚拟机是一个很有优势的工具,可以说反病毒软件是否存在模拟器是衡量反病毒软件能力的一个指标.反病毒虚拟机不光是内嵌在反病毒软件内部,来动态执行样本.这种虚拟机一般也可以单独用来动态执行批量样本,检 ...

  6. php monolog 的写日志到unix domain socket 测试终于成功

    在另外一个客户端执行 php s.php后, 通过nc -lU /tmp/tg.sck 建立的unix domain socket 有接收到消息. <?php require 'vendor/a ...

  7. 最新---java多线程下载文件

    import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; impo ...

  8. jquery 动态添加,降低input表单的方法

    html代码例如以下 <html> <tr><button style="margin-left:10px" class="add_fiel ...

  9. Angular2.x-主/细节组件

    此刻,HeroesComponent显示heroes列表和所选heroes的详细信息. 随着应用程序的增长保持一个组件中的所有功能将不可维护.您需要将大型组件分成更小的子组件,每个组件都专注于特定的任 ...

  10. 熊猫猪新系统測试之二:Mac OS X 10.10 优胜美地

    在第一篇windows 10技术预览版測试之后.本猫为大家呈现还有一个刚刚才更新的mac操作系统:"优胜美地".苹果相同一改以猫科动物为代号命名的传统.在10.9的Maverick ...