本系列文章主要爲我以前所學知識的一次微小的實踐,以我學校圖書館管理系統爲雛形所做。css
本系列文章主要參考資料:html
微軟文檔:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windowsgit
《Pro ASP.NET MVC 5》、《鋒利的 jQuery》github
當此系列文章寫完後會在一週內推出修正版。數據庫
此係列皆使用 VS2017+C# 做爲開發環境。若是有什麼問題或者意見歡迎在留言區進行留言。 編程
項目 github 地址:https://github.com/NanaseRuri/LibraryDemowindows
本章內容:自定義 HtmlHelper、Session 的使用、分頁、數據庫初始化器、取消 int 主鍵自動增加api
1、對圖書信息的域模型進行修改性能優化
因爲在此處我使用了二維碼做爲主鍵,一個二維碼不可能同時放在不一樣的書架上,所以重寫以前創建的多對多的模型。架構
移除 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 }
移除 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 }
爲了可以給書籍添加縮略圖以及更方便的編寫邏輯,爲 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 LibraryDemo 2 add-migration RemoveBookMiddle -c LibraryDemo.Data.LendingInfoDbContext 3 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 books 377 from bookshelf in bookshelfs 378 where book.Location == bookshelf.Location && book.Sort == bookshelf.Sort 379 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 }
在 Configure 方法中調用該數據庫初始化方法:
1 BookInitiator.BookInitial(app.ApplicationServices).Wait();
運行後查看數據庫:
2、圖書借閱主頁面
首先建立一個視圖模型用於肯定分頁信息:
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 BookListViewModel 2 { 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 else 31 { 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>
最終結果: