前言:

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

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

微软文档: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. Linux下出现launch failed.Binary not found的解决方案

    Linux下出现launch failed.Binary not found的解决方案: Project->Properties->C/C++Build->Settings-> ...

  2. Spring注解 @Component、@Repository、@Service、@Controller @Resource、@Autowired、@Qualifier 解析

    @Repository.@Service.@Controller 这几个是一个类型,其实@Component 跟他们也是一个类型的 Spring 2.5 中除了提供 @Component 注释外,还定 ...

  3. XCode 或者ITune 添加账号时,提示:This action could not be completed. 或者 Access Privileges

    当遇到This action could not be completed 或者 You do not have enough access privileges for this operation ...

  4. The Bottom of a Graph

                                    poj——The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K ...

  5. scoi2018游记

    day1: t1点分树 冬令营上jry讲过原题,t2启发式合并+解二次同余方程 预计100+100+0 结果t1卡内存,t2模数太大.导致调试到没有写t3 最后t1 85 t2 15 要是我会o1快速 ...

  6. 240.Search in a 2D Matrix II

    /* * 240.Search in a 2D Matrix II * 2016-6-17by Mingyang * From left-bottom to right-top * 他这道题目虽说是用 ...

  7. 仿苹果app下载动画-煎饼

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Spring Boot使用Spring Data Redis操作Redis(单机/集群)

    说明:Spring Boot简化了Spring Data Redis的引入,只要引入spring-boot-starter-data-redis之后会自动下载相应的Spring Data Redis和 ...

  9. Entity framework自定义字段实现思路

    ublic class MyModel { public int MyModelID { get; set; } public string FixedProperty1 { get; set; } ...

  10. 前端3D、动画相关开源JS

    WebGL http://taobaofed.org/blog/2015/12/21/webgl-handbook/ D3 (或者叫 D3.js )是一个基于 web 标准的 JavaScript 可 ...