前言:
本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作。
本系列文章主要参考资料:
微软文档: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
本章内容:自定义 HtmlHelper、Session 的使用、分页、数据库初始化器、取消 int 主键自动增长
一、对图书信息的域模型进行修改
由于在此处我使用了二维码作为主键,一个二维码不可能同时放在不同的书架上,因此重写之前建立的多对多的模型。
移除 BookMiddle,去除 Book类 中的 ICollection<BookMiddle> 字段,改为 Bookshelf 字段。
1 public class Book 2 { 3 /// <summary> 4 /// 二维码 5 /// </summary> 6 [Key] 7 public string BarCode { get; set; } 8 9 public string ISBN { get; set; }10 11 /// <summary>12 /// 书名13 /// </summary>14 [Required]15 public string Name { get; set; } 16 17 /// <summary>18 /// 取书号19 /// </summary>20 public string FetchBookNumber { get; set; }21 22 /// <summary>23 /// 所在书架24 /// </summary>25 //public Bookshelf Bookshelf { get; set; }26 public Bookshelf Bookshelf { get; set; }27 28 /// <summary>29 /// 借出时间30 /// </summary>31 public DateTime? BorrowTime { get; set; }32 33 /// <summary>34 /// 到期时间35 /// </summary>36 public DateTime? MatureTime { get; set; } 37 38 /// <summary>39 /// 预约最晚借书日期40 /// </summary>41 public DateTime? AppointedLatestTime { get; set; }42 43 /// <summary>44 /// 借阅状态45 /// </summary>46 public BookState State { get; set; } 47 48 /// <summary>49 /// 持有者,指定外键50 /// </summary>51 public Student Keeper { get; set; }52 }
View Code
移除 Bookshelf 类中的 ICollection<BookMiddle> 字段,改为 ICollection<Book> 字段
1 public class Bookshelf 2 { 3 /// <summary> 4 /// 书架ID 5 /// </summary> 6 [Key] 7 public int BookshelfId { get; set; } 8 9 /// <summary>10 /// 书架的书籍类别11 /// </summary>12 13 [Required]14 public string Sort { get; set; } 15 /// <summary>16 /// 最小取书号17 /// </summary>18 [Required]19 public string MinFetchNumber { get; set; }20 [Required]21 public string MaxFetchNumber { get; set; }22 23 /// <summary>24 /// 书架位置25 /// </summary>26 [Required]27 public string Location { get; set; }28 29 /// <summary>30 /// 全部藏书31 /// </summary>32 public ICollection<Book> Books { get; set; }33 }
View Code
为了能够给书籍添加缩略图以及更方便的编写逻辑,为 Book 和 BookDetail 添加多个字段:
1 /// <summary> 2 /// 用于借阅的书籍信息 3 /// </summary> 4 public class Book 5 { 6 /// <summary> 7 /// 二维码 8 /// </summary> 9 [Key][Required(ErrorMessage = "未填写二维码")]10 [Display(Name = "二维码")]11 public string BarCode { get; set; }12 13 public string ISBN { get; set; }14 15 /// <summary>16 /// 书名17 /// </summary>18 [Required]19 [Display(Name = "书名")]20 public string Name { get; set; }21 22 /// <summary>23 /// 取书号24 /// </summary>25 [Display(Name = "取书号")]26 public string FetchBookNumber { get; set; }27 28 /// <summary>29 /// 所在书架30 /// </summary>31 public Bookshelf Bookshelf { get; set; }32 33 [Display(Name = "书架号")]34 public int BookshelfId { get; set; }35 36 /// <summary>37 /// 借出时间38 /// </summary>39 [Display(Name = "借出时间")]40 public DateTime? BorrowTime { get; set; }41 42 /// <summary>43 /// 到期时间44 /// </summary>45 [Display(Name = "到期时间")]46 public DateTime? MatureTime { get; set; }47 48 /// <summary>49 /// 预约最晚借书日期50 /// </summary>51 [Display(Name = "预约取书时间")]52 public DateTime? AppointedLatestTime { get; set; }53 54 /// <summary>55 /// 借阅状态56 /// </summary>57 [Display(Name = "书籍状态")]58 public BookState State { get; set; }59 60 /// <summary>61 /// 持有者,指定外键62 /// </summary>63 public Student Keeper { get; set; }64 [Display(Name = "持有者学号")]65 public string KeeperId { get; set; }66 67 [Display(Name = "位置")]68 public string Location { get; set; }69 70 [Display(Name = "分类")]71 public string Sort { get; set; }72 }
1 /// <summary> 2 /// 书籍自身的详细信息 3 /// </summary> 4 public class BookDetails 5 { 6 [Key] 7 public string ISBN { get; set; } 8 [Required] 9 public string Name { get; set; }10 [Required]11 public string Author { get; set; }12 [Required]13 public string Press { get; set; }14 [Required]15 public string FetchBookNumber { get; set; } 16 /// <summary>17 /// 出版时间18 /// </summary>19 [Required]20 public DateTime PublishDateTime{ get; set; }21 22 /// <summary>23 /// 书籍版本24 /// </summary>25 [Required]26 public int Version { get; set; }27 28 /// <summary>29 /// 载体形态,包括页数、媒介等信息30 /// </summary>31 public string SoundCassettes { get; set; }32 33 /// <summary>34 /// 简介35 /// </summary>36 public string Description { get; set; }37 38 39 /// <summary>40 /// 缩略图41 /// </summary>42 public byte[] ImageData { get; set; }43 public string ImageMimeType { get; set; }44 }
由于 EF 会自动将 int 类型的主键设置为自动增长,因此自定义 Bookshelf 的 ID 在插入数据库时会报错,在此需添加修饰 [DatabaseGenerated(DatabaseGeneratedOption.None)] 告知 ef 取消该设置:
1 public class Bookshelf 2 { 3 /// <summary> 4 /// 书架ID 5 /// </summary> 6 [Key] 7 //不自动增长 8 [DatabaseGenerated(DatabaseGeneratedOption.None)] 9 public int BookshelfId { get; set; }10 11 /// <summary>12 /// 书架的书籍类别13 /// </summary>14 15 [Required]16 public string Sort { get; set; } 17 /// <summary>18 /// 最小取书号19 /// </summary>20 [Required]21 public string MinFetchNumber { get; set; }22 [Required]23 public string MaxFetchNumber { get; set; }24 25 /// <summary>26 /// 书架位置27 /// </summary>28 [Required]29 public string Location { get; set; }30 31 /// <summary>32 /// 全部藏书33 /// </summary>34 public ICollection<Book> Books { get; set; }35 }
然后添加迁移并更新数据库,若更新失败在此选择移除数据库以及迁移再执行该步骤,生产中应当备份原文件:
1 cd LibraryDemo2 add-migration RemoveBookMiddle -c LibraryDemo.Data.LendingInfoDbContext3 update-database -c LibraryDemo.Data.LendingInfoDbContext
新建 BookInitiator 用于初始化该数据库,在这里会报一个 Book 重复主键的错误,不知道为什么但是数据确实全都插进去了:
1 public class BookInitiator 2 { 3 public static async Task BookInitial(IServiceProvider serviceProvider) 4 { 5 LendingInfoDbContext context = serviceProvider.GetRequiredService<LendingInfoDbContext>(); 6 if (!context.Books.Any() || !context.Bookshelves.Any()) 7 { 8 Bookshelf[] bookshelfs = new[] 9 { 10 new Bookshelf() 11 { 12 BookshelfId = 1, 13 Location = "主校区", 14 Sort = "计算机" 15 }, 16 new Bookshelf() 17 { 18 BookshelfId = 2, 19 Location = "主校区", 20 Sort = "文学" 21 }, 22 new Bookshelf() 23 { 24 BookshelfId = 3, 25 Location = "东校区", 26 Sort = "计算机" 27 }, 28 new Bookshelf() 29 { 30 BookshelfId = 4, 31 Location = "阅览室", 32 Sort = "文学" 33 }, 34 new Bookshelf() 35 { 36 BookshelfId = 5, 37 Location = "阅览室", 38 Sort = "计算机" 39 }, 40 }; 41 42 Book[] books = new[] 43 { 44 new Book() 45 { 46 Name = "精通ASP.NET MVC 5", 47 BarCode = "001100987211", 48 ISBN = "978-7-115-41023-8", 49 State = BookState.Normal, 50 FetchBookNumber = "TP393.092 19", 51 Location = "主校区", 52 Sort = "计算机" 53 }, 54 new Book() 55 { 56 Name = "精通ASP.NET MVC 5", 57 BarCode = "001100987212", 58 ISBN = "978-7-115-41023-8", 59 State = BookState.Normal, 60 FetchBookNumber = "TP393.092 19", 61 Location = "主校区", 62 Sort = "计算机" 63 }, 64 new Book() 65 { 66 Name = "精通ASP.NET MVC 5", 67 BarCode = "001100987213", 68 ISBN = "978-7-115-41023-8", 69 State = BookState.Normal, 70 FetchBookNumber = "TP393.092 19", 71 Location = "东校区", 72 Sort = "计算机" 73 }, 74 new Book() 75 { 76 Name = "精通ASP.NET MVC 5", 77 BarCode = "001100987214", 78 ISBN = "978-7-115-41023-8", 79 State = BookState.Readonly, 80 FetchBookNumber = "TP393.092 19", 81 Location = "阅览室", 82 Sort = "计算机" 83 }, 84 new Book() 85 { 86 Name = "Entity Framework实用精要", 87 BarCode = "001101279682", 88 ISBN = "978-7-302-48593-3", 89 State = BookState.Normal, 90 FetchBookNumber = "TP393.09 447", 91 Location = "主校区", 92 Sort = "计算机" 93 }, 94 new Book() 95 { 96 Name = "Entity Framework实用精要", 97 BarCode = "001101279683", 98 ISBN = "978-7-302-48593-3", 99 State = BookState.Normal,100 FetchBookNumber = "TP393.09 447",101 Location = "主校区",102 Sort = "计算机"103 },104 new Book()105 {106 Name = "Entity Framework实用精要",107 BarCode = "001101279684",108 ISBN = "978-7-302-48593-3",109 State = BookState.Normal,110 FetchBookNumber = "TP393.09 447",111 Location = "东校区",112 Sort = "计算机"113 },114 new Book()115 {116 Name = "Entity Framework实用精要",117 BarCode = "001101279685",118 ISBN = "978-7-302-48593-3",119 State = BookState.Normal,120 FetchBookNumber = "TP393.09 447",121 Location = "东校区",122 Sort = "计算机"123 },124 new Book()125 {126 Name = "Entity Framework实用精要",127 BarCode = "001101279686",128 ISBN = "978-7-302-48593-3",129 State = BookState.Normal,130 FetchBookNumber = "TP393.09 447",131 Location = "阅览室",132 Sort = "计算机"133 },134 new Book()135 {136 Name = "Rails 5敏捷开发",137 BarCode = "001101290497",138 ISBN = "978-7-5680-3659-7",139 State = BookState.Normal,140 FetchBookNumber = "TP393.09 448",141 Location = "主校区",142 Sort = "计算机"143 },144 new Book()145 {146 Name = "Rails 5敏捷开发",147 BarCode = "001101290498",148 ISBN = "978-7-5680-3659-7",149 State = BookState.Normal,150 FetchBookNumber = "TP393.09 448",151 Location = "主校区",152 Sort = "计算机"153 },154 new Book()155 {156 Name = "Rails 5敏捷开发",157 BarCode = "001101290499",158 ISBN = "978-7-5680-3659-7",159 State = BookState.Readonly,160 FetchBookNumber = "TP393.09 448",161 Location = "主校区",162 Sort = "计算机"163 },164 new Book()165 {166 Name = "你必须掌握的Entity Framework 6.x与Core 2.0",167 BarCode = "001101362986",168 ISBN = "978-7-5680-3659-7",169 State = BookState.Normal,170 FetchBookNumber = "TP393.09 452",171 Location = "主校区",172 Sort = "计算机"173 },174 new Book()175 {176 Name = "你必须掌握的Entity Framework 6.x与Core 2.0",177 BarCode = "001101362987",178 ISBN = "978-7-5680-3659-7",179 State = BookState.Readonly,180 FetchBookNumber = "TP393.09 452",181 Location = "主校区",182 Sort = "计算机"183 },184 new Book()185 {186 Name = "毛选. 第一卷",187 BarCode = "00929264",188 ISBN = "7-01-000922-8",189 State = BookState.Normal,190 FetchBookNumber = "A41 1:1",191 Location = "主校区",192 Sort = "文学"193 },194 new Book()195 {196 Name = "毛选. 第一卷",197 BarCode = "00929265",198 ISBN = "7-01-000922-8",199 State = BookState.Normal,200 FetchBookNumber = "A41 1:1",201 Location = "主校区",202 Sort = "文学"203 },204 new Book()205 {206 Name = "毛选. 第一卷",207 BarCode = "00929266",208 ISBN = "7-01-000922-8",209 State = BookState.Readonly,210 FetchBookNumber = "A41 1:1",211 Location = "阅览室",212 Sort = "文学"213 },214 new Book()215 {216 Name = "毛选. 第二卷",217 BarCode = "00929279",218 ISBN = "7-01-000915-5",219 State = BookState.Normal,220 FetchBookNumber = "A41 1:2",221 Location = "主校区",222 Sort = "文学"223 },224 new Book()225 {226 Name = "毛选. 第二卷",227 BarCode = "00929280",228 ISBN = "7-01-000915-5",229 State = BookState.Readonly,230 FetchBookNumber = "A41 1:2",231 Location = "阅览室",232 Sort = "文学"233 },234 new Book()235 {236 Name = "毛选. 第三卷",237 BarCode = "00930420",238 ISBN = "7-01-000916-3",239 State = BookState.Normal,240 FetchBookNumber = "A41 1:3",241 Location = "主校区",242 Sort = "文学"243 },244 new Book()245 {246 Name = "毛选. 第三卷",247 BarCode = "00930421",248 ISBN = "7-01-000916-3",249 State = BookState.Readonly,250 FetchBookNumber = "A41 1:3",251 Location = "阅览室",252 Sort = "文学"253 },254 new Book()255 {256 Name = "毛选. 第四卷",257 BarCode = "00930465",258 ISBN = "7-01-000925-2",259 State = BookState.Normal,260 FetchBookNumber = "A41 1:4",261 Location = "主校区",262 Sort = "文学"263 },264 new Book()265 {266 Name = "毛选. 第四卷",267 BarCode = "00930466",268 ISBN = "7-01-000925-2",269 State = BookState.Readonly,270 FetchBookNumber = "A41 1:4",271 Location = "阅览室",272 Sort = "文学"273 }274 };275 276 BookDetails[] bookDetails = new[]277 {278 new BookDetails()279 {280 Author = "Admam Freeman",281 Name = "精通ASP.NET MVC 5",282 ISBN = "978-7-115-41023-8",283 Press = "人民邮电出版社",284 PublishDateTime = new DateTime(2016,1,1),285 SoundCassettes = "13, 642页 : 图 ; 24cm",286 Version = 1,287 FetchBookNumber = "TP393.092 19",288 Description = "ASP.NET MVC 5框架是微软ASP.NET Web平台的新进展。它提供了高生产率的编程模型,结合ASP.NET的全部优势,促成更整洁的代码架构、测试驱动开发和强大的可扩展性。本书涵盖ASP.NET MVC 5的所有开发优势技术,包括用C#属性定义路由技术及重写过滤器技术等。且构建MVC应用程序的用户体验也有本质上的改进。其中书里也专一讲解了用新Visual Studio 2013创建MVC应用程序时的技术和技巧。本书包括完整的开发工具介绍以及对代码进行辅助编译和调试的技术。本书还涉及流行的Bootstrap JavaScript库,该库现已被纳入到MVC 5之中,为开发人员提供更广泛的多平台CSS和HTML5选项,而不必像以前那样去加载大量的第三方库。"289 },290 new BookDetails()291 {292 Author = "吕高旭",293 Name = "Entity Framework实用精要",294 ISBN = "978-7-302-48593-3",295 Press = "清华大学出版社",296 PublishDateTime = new DateTime(2018,1,1),297 SoundCassettes = "346页 ; 26cm",298 Version = 1,299 FetchBookNumber = "TP393.09 447",300 Description = "本书通过介绍Entity Framework与 LINQ 开发实战的案例,以 Entity Framework 技术内容的讨论为主线,结合关键的 LINQ技巧说明,提供读者系统性学习 Entity Framework 所需的内容。本书旨在帮助读者进入 Entity Framework的世界,建立必要的技术能力,同时希望读者在完成本书的教学课程之后,能够更进一步地将其运用在实际的项目开发中。"301 },302 new BookDetails()303 {304 Author = "鲁比",305 Name = "Rails 5敏捷开发",306 ISBN = "978-7-5680-3659-7",307 Press = "华中科技大学出版社",308 PublishDateTime = new DateTime(2018,1,1),309 SoundCassettes = "xxi, 451页 : 图 ; 23cm",310 Version = 1,311 FetchBookNumber = "TP393.09 448",312 Description = "本书以讲解“购书网站”案例为主线, 逐步介绍Rails的内置功能。全书分为3部分, 第一部分介绍Rails的安装、应用程序验证、Rails框架的体系结构, 以及Ruby语言知识; 第二部分用迭代方式构建应用程序, 然后依据敏捷开发模式开展测试, 最后用Capistrano完成部署; 第三部分补充日常实用的开发知识。本书既有直观的示例, 又有深入的分析, 同时涵盖了Web开发各方面的知识, 堪称一部内容全面而又深入浅出的佳作。第5版增加了关于Rails 5和Ruby 2.2新特性和最佳实践的内容。"313 },314 new BookDetails()315 {316 Author = "汪鹏",317 Name = "你必须掌握的Entity Framework 6.x与Core 2.0",318 ISBN = "978-7-302-50017-9",319 Press = "清华大学出版社",320 PublishDateTime = new DateTime(2018,1,1),321 SoundCassettes = "X, 487页 : 图 ; 26cm",322 Version = 1,323 FetchBookNumber = "TP393.09 452",324 Description = "本书分为四篇,第一篇讲解Entity Framework 6.x的基础,包括数据库表的创建,数据的操作和数据加载方式。第二篇讲解Entity Framework 6.x进阶,包括基本原理和性能优化。第三篇讲解跨平台Entity Framework Core 2.x的基础知识和开发技巧。第四篇讲解在Entity Framework Core 2.x中解决并发问题,并给出实战开发案例。"325 },326 new BookDetails()327 {328 Author = "毛",329 Name = "毛选. 第一卷",330 ISBN = "7-01-000914-7",331 Press = "人民出版社",332 PublishDateTime = new DateTime(1991,1,1),333 SoundCassettes = "340页 : 肖像 ; 19厘米",334 FetchBookNumber = "A41 1:1",335 Version = 2,336 Description = "《毛选》是对20世纪中国影响最大的书籍之一。"337 },338 new BookDetails()339 {340 Author = "毛",341 Name = "毛选. 第二卷",342 ISBN = "7-01-000915-5",343 Press = "人民出版社",344 PublishDateTime = new DateTime(1991,1,1),345 SoundCassettes = "343-786页 : 肖像 ; 19厘米",346 Version = 2,347 FetchBookNumber = "A41 1:2",348 Description = "《毛选》是对20世纪中国影响最大的书籍之一。"349 },350 new BookDetails()351 {352 Author = "毛",353 Name = "毛选. 第三卷",354 ISBN = "7-01-000916-3",355 Press = "人民出版社",356 PublishDateTime = new DateTime(1991,1,1),357 SoundCassettes = "789?±1120页 ; 20厘米",358 FetchBookNumber = "A41 1:3",359 Version = 2,360 Description = "《毛选》是对20世纪中国影响最大的书籍之一。"361 },362 new BookDetails()363 {364 Author = "毛",365 Name = "毛选. 第四卷",366 ISBN = "7-01-000925-2",367 Press = "人民出版社",368 PublishDateTime = new DateTime(1991,1,1),369 SoundCassettes = "1123?±1517页 ; 20厘米",370 FetchBookNumber = "A41 1:4",371 Version = 2,372 Description = "《毛选》是对20世纪中国影响最大的书籍之一。"373 },374 };375 376 var temp = from book in books377 from bookshelf in bookshelfs378 where book.Location == bookshelf.Location && book.Sort == bookshelf.Sort379 select new { BarCode = book.BarCode, BookshelfId = bookshelf.BookshelfId };380 381 foreach (var bookshelf in bookshelfs)382 {383 bookshelf.Books=new List<Book>();384 }385 386 foreach (var tem in temp)387 {388 Bookshelf targetShelf = bookshelfs.Single(bookshelf => bookshelf.BookshelfId == tem.BookshelfId);389 Book targetBook = books.Single(book => book.BarCode == tem.BarCode);390 targetShelf.Books.Add(targetBook);391 }392 393 foreach (var bookshelf in bookshelfs)394 {395 bookshelf.MaxFetchNumber=bookshelf.Books.Max(b => b.FetchBookNumber);396 bookshelf.MinFetchNumber=bookshelf.Books.Min(b => b.FetchBookNumber);397 }398 399 foreach (var bookshelf in bookshelfs)400 {401 await context.Bookshelves.AddAsync(bookshelf);402 await context.SaveChangesAsync();403 }404 405 foreach (var bookDetail in bookDetails)406 {407 await context.BooksDetail.AddAsync(bookDetail);408 await context.SaveChangesAsync();409 }410 411 foreach (var book in books)412 {413 await context.Books.AddAsync(book);414 await context.SaveChangesAsync();415 }416 }417 }418 }
View Code
在 Configure 方法中调用该数据库初始化方法:
1 BookInitiator.BookInitial(app.ApplicationServices).Wait();
运行后查看数据库:
二、图书借阅主页面
首先创建一个视图模型用于确定分页信息:
1 public class PagingInfo 2 { 3 public int TotalItems { get; set; } 4 public int ItemsPerPage { get; set; } 5 public int CurrentPage { get; set; } 6 7 public int TotalPages 8 { 9 get => (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage);10 }11 }
然后创建另一个视图模型用于确定该分页信息以及各分页的书籍:
1 public class BookListViewModel2 {3 public IEnumerable<BookDetails> BookDetails { get; set; }4 public PagingInfo PagingInfo { get; set; }5 }
创建一个自定义 HtmlHelper 用于在视图中使用 Razor 语法获取分页,在 ASP.NET Core 中 TagBuilder 继承自 IHtmlContent,不能直接对 TagBuilder 进行赋值,需调用 MergeAttribute 方法和 InnerHtml 属性的 AppendHtml 方法编写标签;并且 TagBuilder 没有实现 ToString 方法,只能通过其 WriteTo 方法将内容写到一个 TextWriter 对象中以取出其值:
1 public static class PagingHelper 2 { 3 public static HtmlString PageLinks(this IHtmlHelper html, PagingInfo pagingInfo, Func<int, string> pageUrl) 4 { 5 StringWriter writer=new StringWriter(); 6 for (int i = 1; i <= pagingInfo.TotalPages; i++) 7 { 8 TagBuilder tag=new TagBuilder("a"); 9 tag.MergeAttribute("href",pageUrl(i));10 tag.InnerHtml.AppendHtml(i.ToString());11 if (i==pagingInfo.CurrentPage)12 {13 tag.AddCssClass("selected");14 tag.AddCssClass("btn-primary");15 }16 tag.AddCssClass("btn btn-default");17 tag.WriteTo(writer,HtmlEncoder.Default);18 }19 return new HtmlString(writer.ToString());20 }21 }
创建 BookInfo 控制器并确定其中每个分页的书籍数,使用 Session 获取更快地获取书籍信息:
1 public class BookInfoController : Controller 2 { 3 private LendingInfoDbContext _context; 4 private static int amout = 4; 5 6 public BookInfoController(LendingInfoDbContext context) 7 { 8 _context = context; 9 }10 11 public IActionResult Index(string category, int page = 1)12 {13 IEnumerable<BookDetails> books = null;14 if (HttpContext.Session != null)15 {16 books = HttpContext.Session.Get<IEnumerable<BookDetails>>("bookDetails");17 }18 if (books == null)19 {20 books = _context.BooksDetail;21 HttpContext.Session?.Set<IEnumerable<BookDetails>>("books", books);22 }23 BookListViewModel model = new BookListViewModel()24 {25 PagingInfo = new PagingInfo()26 {27 ItemsPerPage = amout,28 TotalItems = books.Count(),29 CurrentPage = page,30 },31 BookDetails = books.OrderBy(b => b.FetchBookNumber).Skip((page - 1) * amout).Take(amout)32 }; 33 return View(model);34 }35 36 public FileContentResult GetImage(string isbn)37 {38 BookDetails target = _context.BooksDetail.FirstOrDefault(b => b.ISBN == isbn);39 if (target != null)40 {41 return File(target.ImageData, target.ImageMimeType);42 }43 return null;44 }45 }
视图页面:
24 行利用 BookListViewModel 中 PagingInfo 的 CurrentPage 获取各序号,32 行中使 img 元素的 src 指向 BookInfoController 的 GetImage 方法以获取图片:
1 @using LibraryDemo.TagHelpers 2 @model BookListViewModel 3 @{ 4 ViewData["Title"] = "Index"; 5 int i = 1; 6 } 7 <style type="text/css"> 8 tr > td { 9 padding: 5px;10 padding-left: 20px;11 }12 tr+tr {13 border-top: thin solid black;14 padding-top: 10px;15 }16 </style>17 18 <hr />19 <table>20 <tbody>21 @foreach (var book in Model.BookDetails)22 {23 <tr>24 <td style="width: 3%">@((@Model.PagingInfo.CurrentPage-1)*4+i++)</td>25 <td style="text-align: center; width: 150px; height: 200px;">26 @if (book.ImageData == null)27 {28 <label>No Image</label>29 }30 else31 {32 <img class="img-thumbnail pull-left" src="@Url.Action("GetImage", "BookInfo", new {book.ISBN})" />33 } 34 </td>35 <td style="text-align: left;">36 <a style="margin-left: 1em;">@book.Name</a>37 <div style="margin-left: 2em;margin-top: 5px">38 <span>@book.Author</span>39 <br />40 <span>@book.Press</span>41 <p>@book.FetchBookNumber</p>42 </div>43 <div style="text-indent: 2em">44 <p>@book.Description</p>45 </div>46 </td>47 </tr>48 }49 </tbody> 50 </table> 51 <div class="btn-group pull-right">52 @Html.PageLinks(Model.PagingInfo, x => Url.Action("Index", new { page = x}))53 </div>
最终结果: