From 2c695da18f88ee04e6016fa9f5c3ce2ae5a7bb5f Mon Sep 17 00:00:00 2001 From: "tracyleecore@gmail.com" Date: Thu, 3 Dec 2020 14:27:06 +0800 Subject: [PATCH 1/2] Implement Repository Pattern, BoardInfo as sample --- BILib/BoardBl.cs | 106 +++-- BILib/BoardHelper.cs | 3 + BILib/BoardHelper_DI.cs | 483 ++++++++++++++++++++++ BILib/Repository/BoardInfoRepository.cs | 38 ++ BILib/Repository/GenericRepository.cs | 76 ++++ BILib/Repository/PostRankRepository.cs | 11 + DBModel/SqlModels/BoardInfo.cs | 4 +- DBModel/SqlModels/MWDBContext.cs | 2 +- middleware/Controllers/BoardController.cs | 29 +- middleware/NLog.config | 15 + middleware/Program.cs | 10 +- middleware/Startup.cs | 21 +- 12 files changed, 700 insertions(+), 98 deletions(-) create mode 100644 BILib/BoardHelper_DI.cs create mode 100644 BILib/Repository/BoardInfoRepository.cs create mode 100644 BILib/Repository/GenericRepository.cs create mode 100644 BILib/Repository/PostRankRepository.cs create mode 100644 middleware/NLog.config diff --git a/BILib/BoardBl.cs b/BILib/BoardBl.cs index d5de14b..817bc81 100644 --- a/BILib/BoardBl.cs +++ b/BILib/BoardBl.cs @@ -1,12 +1,9 @@ -using DBModel; -using DBModel.SqlModels; +using DBModel.SqlModels; using DtoModel; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace BILib { @@ -15,18 +12,17 @@ namespace BILib /// public class BoardBl { - private MWDBContext _dbContext; - private List _data; + private readonly BoardInfoRepository _repository; + private readonly ILogger _logger; /// /// Constructor /// /// - public BoardBl(MWDBContext context) + public BoardBl(BoardInfoRepository repository, ILogger logger) { - _dbContext = context; - - SetFakeData(); + _repository = repository; + _logger = logger; } /// @@ -37,7 +33,8 @@ public BoardBl(MWDBContext context) /// 看板清單 public IEnumerable GetBoards() { - return _dbContext.BoardInfo.ToDtos(); + return _repository.GetAsNoTracking() + .ToDtos(); } /// @@ -47,7 +44,9 @@ public IEnumerable GetBoards() /// 看板 public BoardDto GetBoard(string name) { - return _dbContext.BoardInfo.SingleOrDefault(p => p.Board == name).ToDto(); + return _repository.GetAsNoTracking() + .SingleOrDefault(p => p.Board == name) + .ToDto(); } /// @@ -57,7 +56,9 @@ public BoardDto GetBoard(string name) /// 符合的看板清單 public IEnumerable SearchBoards(string keyword) { - return _dbContext.BoardInfo.Where(p => p.Board.Contains(keyword)).ToDtos(); + return _repository.GetAsNoTracking() + .Where(p => p.Board.Contains(keyword)) + .ToDtos(); } /// @@ -68,19 +69,27 @@ public IEnumerable SearchBoards(string keyword) /// 熱門看板清單 public IEnumerable GetPopularBoards(int page, int count) { - return _data.Skip((page - 1) * count).Take(count); + return _repository.GetAsNoTracking() + //.Where(b => b) // TODO: 熱門看板的條件 + .Skip((page - 1) * count) + .Take(count) + .ToDtos(); } /// /// 取得我的最愛看板清單 /// - /// 使用者帳號 + /// 使用者帳號 /// 頁數 /// 每頁數量 /// 我的最愛看板清單 - public IEnumerable GetFavoriteBoards(string id, int page, int count) + public IEnumerable GetFavoriteBoards(string userId, int page, int count) { - return _data.Skip((page - 1) * count).Take(count); + return _repository.GetAsNoTracking() + //.Where(b => b) // TODO: 最愛看板的條件 + .Skip((page - 1) * count) + .Take(count) + .ToDtos(); } /// @@ -92,7 +101,11 @@ public IEnumerable GetFavoriteBoards(string id, int page, int count) /// 看板清單 public IEnumerable GetCategoryBoards(string name, int page, int count) { - return _data.Skip((page - 1) * count).Take(count); + return _repository.GetAsNoTracking() + //.Where(b => b) // TODO: 分類名稱條件 + .Skip((page - 1) * count) + .Take(count) + .ToDtos(); } /// @@ -100,45 +113,13 @@ public IEnumerable GetCategoryBoards(string name, int page, int count) /// /// 看板名稱 /// 板主名單 - public string[] GetBoardModerators(string name) - { - var board = _dbContext.BoardInfo.SingleOrDefault(x => x.Board == name); - if (board == null) return null; - - var result = board.ToDto().Moderators.Select(p => p.Id).ToArray(); - return result; - } - - /// - /// 建假資料 - /// - private void SetFakeData() + public IEnumerable GetBoardModerators(string name) { - _data = new List(); - for (int i = 1; i <= 100; i++) - { - var moderators = new List(); - for (int j = 1; j <= 3; j++) - { - moderators.Add(new UserDto - { - Sn = j, - Id = $"Ptter{j}", - NickName = $"NickName{j}", - Money = 100 * j - }); - } - - _data.Add(new BoardDto - { - Sn = i, - Name = $"Test{i}", - BoardType = BoardType.Board, - Title = $"[Test{i}] 測試板{i}", - OnlineCount = 10 * i, - Moderators = moderators - }); - } + return _repository.GetAsNoTracking() + .SingleOrDefault(b => b.Board == name)? + .ToDto() + .Moderators? + .Select(p => p.Id); } } @@ -169,18 +150,23 @@ public static BoardDto ToDto(this BoardInfo source) public static IQueryable ToDtos(this IQueryable source) { var results = source.Select(p => p.ToDto()); + return results; + } + public static IQueryable ToDtos(this IEnumerable source) + { + var results = source.AsQueryable() + .Select(p => p.ToDto()); return results; } } public static class BoardDtoExtension { - public static List SetSerialNumber(this IEnumerable source) + public static IEnumerable SetSerialNumber(this IEnumerable source) { - var sn = 1; + int sn = 1; var list = source.ToList(); - list.ForEach(p => p.Sn = sn++); return list; diff --git a/BILib/BoardHelper.cs b/BILib/BoardHelper.cs index bd8c3b0..8280671 100644 --- a/BILib/BoardHelper.cs +++ b/BILib/BoardHelper.cs @@ -14,6 +14,9 @@ namespace BILib { + /// + /// TODO: 未來預期被 BoardHelper_DI 取代;改為 DI 方式 + /// public class BoardHelper { private NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/BILib/BoardHelper_DI.cs b/BILib/BoardHelper_DI.cs new file mode 100644 index 0000000..1eaf700 --- /dev/null +++ b/BILib/BoardHelper_DI.cs @@ -0,0 +1,483 @@ +using DBModel; +using DBModel.SqlModels; +using DtoModel; +using HtmlAgilityPack; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; + +namespace BILib +{ + public class BoardHelper_DI + { + private readonly BoardInfoRepository _boardDtoRepository; + private readonly PostRankRepository _postRankRepository; + private readonly ILogger _logger; + + public BoardHelper_DI(BoardInfoRepository boardDtoRepository, + PostRankRepository postRankRepository, + ILogger logger) + { + _boardDtoRepository = boardDtoRepository; + _postRankRepository = postRankRepository; + _logger = logger; + } + + #region + + public IEnumerable GetPopularBoards() + { + const string URL = @"https://www.ptt.cc/bbs/hotboards.html"; + _logger.LogInformation(MethodBase.GetCurrentMethod().Name); + + try + { + var html = new MyWebClient().DownloadString(URL); + var doc = new HtmlDocument(); doc.LoadHtml(HttpUtility.HtmlDecode(html)); + var sequence = 1; + + return doc.DocumentNode.SelectNodes("//a[@class='board']").Select(node => new BoardDto() + { + Sn = sequence++, + Name = node.SelectSingleNode("div[@class='board-name']")?.InnerText, + BoardType = BoardType.Board, + OnlineCount = int.Parse(node.SelectSingleNode("div/span")?.InnerText), + Title = node.SelectSingleNode("div[@class='board-title']")?.InnerText, + + }); + } + catch (Exception ex) + { + _logger.LogDebug($"{MethodBase.GetCurrentMethod().Name}[Exception]:{ex.Message}"); + _logger.LogDebug(ex.StackTrace); + } + + return Enumerable.Empty(); + } + + public APagePosts GetNewPostListByBoardName(string boardName, int page = 1) + { + var boardInfo = _boardDtoRepository.Get().SingleOrDefault(p => p.Board == boardName); + if (boardInfo == null) return null; + + var pagePosts = new APagePosts + { + BoardInfo = new Board + { + Name = boardInfo.Board, + Href = $"/bbs/{boardInfo.Board}/index.html", + Nuser = boardInfo.OnlineUser.ToString(), + Class = "", + Title = boardInfo.ChineseDes, + MaxSize = GetPageSize(boardName) + } + }; + + pagePosts.Page = page; + _logger.LogInformation($"{MethodBase.GetCurrentMethod().Name}[boardName]:{boardName}"); + string text = string.Empty; + string strPage = GetPageNo(page, pagePosts.BoardInfo.MaxSize); + + string url = $"https://www.ptt.cc/bbs/{boardName}/index{strPage}.html"; + MyWebClient client = new MyWebClient(); + client.Encoding = Encoding.UTF8; // 設定Webclient.Encoding + + string html = "未知"; + try + { + html = client.DownloadString(url); + + Dictionary dicRow = new Dictionary(); + + HtmlDocument doc = new HtmlDocument(); + doc.LoadHtml(html); + HtmlDocument doctag = new HtmlDocument(); + int i = 1; + int iwide = 0; + var metaTags = doc.DocumentNode.SelectNodes("//div"); + if (metaTags != null) + { + foreach (var tag in metaTags) + { + + if (tag.Attributes["class"] != null) + { + if (tag.Attributes["class"].Value == "btn-group btn-group-paging") + { + doctag.LoadHtml(tag.OuterHtml); + HtmlNodeCollection htmlNodes = doctag.DocumentNode.SelectNodes("//a[@class='btn wide']"); + foreach (var N in htmlNodes) + { + iwide = N.OuterHtml.IndexOf("/index"); + if (iwide > 0) + { + text = N.OuterHtml.Substring(iwide, N.OuterHtml.Length - iwide); + text = Regex.Replace(text, "[^0-9]", ""); //僅保留數字 + int.TryParse(text, out iwide); + if (pagePosts.BoardInfo.MaxSize < iwide) + pagePosts.BoardInfo.MaxSize = iwide; + } + } + + + } + + if (tag.Attributes["class"].Value == "r-ent") + { + ////class="title" class="author" class="date" + doctag.LoadHtml(tag.OuterHtml); + APost row = new APost(); + HtmlNode bodyNodes = doctag.DocumentNode.SelectSingleNode("//div[@class='title']/a[@href]"); + if (bodyNodes == null) continue; + row.Href = bodyNodes.Attributes["href"].Value; + row.Title = bodyNodes.InnerText; + HtmlNode authorNode = doctag.DocumentNode.SelectSingleNode("//div[@class='author']"); + row.Author = authorNode.InnerText; + HtmlNode dateNode = doctag.DocumentNode.SelectSingleNode("//div[@class='date']"); + row.Date = dateNode.InnerText; + //--AidConverter + row.AID = AidConverter.urlToAid(row.Href); + row.Board = boardName; + List postRanks = _postRankRepository.Get().Where(x => x.Board == boardName && x.Aid == row.AID).ToList(); + if (postRanks.Any()) + { + row.Goup = postRanks.Count(x => x.Rank == 1); + row.Down = postRanks.Count(x => x.Rank == -1); + } + //-- + dicRow.Add(i, row); + i++; + } + else if (tag.Attributes["class"].Value == "r-list-sep") + { + break; + } + + + } + + + } + + } + + pagePosts.PostList = dicRow.Values.ToList(); + + } + catch (Exception ex) + { + pagePosts.Message = new Message + { + Error = $"{ex.Message}.{ex.StackTrace}" + }; + + _logger.LogDebug($"GetNewPostListByBoardName[Exception]:{ex.Message}"); + _logger.LogDebug(ex.StackTrace); + } + + return pagePosts; + } + + public OnePost GetPost(string BoardName, string Filename) + { + _logger.LogInformation($"GetPost[BoardName]:{BoardName}|[Filename]:{Filename}"); + string text = string.Empty; + string url = $"https://www.ptt.cc/bbs/{BoardName}/{Filename}.html"; + MyWebClient client = new MyWebClient(); + client.Encoding = Encoding.UTF8; // 設定Webclient.Encoding + + OnePost post = new OnePost(); + post.Href = url; + post.Board = BoardName; + string html = "未知"; + try + { + html = client.DownloadString(url); + + List iteamList = new List(); + + HtmlDocument doc = new HtmlDocument(); + doc.LoadHtml(html); + HtmlDocument doctag = new HtmlDocument(); + var metaTags = doc.DocumentNode.SelectNodes("//div[@id='main-content']"); + if (metaTags != null) + { + foreach (var tag in metaTags) + { + + if (tag.Attributes["class"] != null) + { + if (tag.Attributes["class"].Value == "bbs-screen bbs-content") + { + ////class="title" class="author" class="date" + doctag.LoadHtml(tag.OuterHtml); + + HtmlNodeCollection metaline = doctag.DocumentNode.SelectNodes("//div[@class='article-metaline']"); + foreach (var dtag in metaline) + { + if (dtag == null) continue; + + switch (dtag.ChildNodes[0].InnerText) + { + case "作者": + string strAuthor = dtag.ChildNodes[1].InnerText; + string[] sA = strAuthor.Split('('); + post.Author = sA[0].Trim(); + if (sA.Length > 1) + post.Nickname = sA[1].Replace(")", ""); + continue; + case "標題": + post.Title = dtag.ChildNodes[1].InnerText; + continue; + case "時間": + post.Date = dtag.ChildNodes[1].InnerText; + continue; + default: + continue; + } + } + + post.Comments = new List(); + metaline = doctag.DocumentNode.SelectNodes("//div[@class='push']"); + if (metaline != null) + { + foreach (var dtag in metaline) + { + if (dtag == null) continue; + + Comment push = new Comment(); + push.Tag = dtag.ChildNodes[0].InnerText.Trim(); + push.Userid = dtag.ChildNodes[1].InnerText; + push.Content = dtag.ChildNodes[2].InnerText; + push.IPdatetime = dtag.ChildNodes[3].InnerText; + post.Comments.Add(push); + } + } + StringBuilder sb = new StringBuilder(); + string[] Content = WebUtility.HtmlDecode(tag.InnerText).Split('\n'); + + foreach (var str in Content.Skip(1)) + { + if (str.IndexOf("※ 發信站") > -1) break; + if (str.IndexOf("※ 編輯") > -1) break; + sb.AppendLine(str); + } + post.Content = sb.ToString(); + + } + + } + } + } + + + text = Newtonsoft.Json.JsonConvert.SerializeObject(post); + + //Console.WriteLine(text); + + } + catch (Exception ex) + { + //Console.WriteLine(ex.Message); + _logger.LogDebug($"GetPost[Exception]:{ex.Message}"); + _logger.LogDebug(ex.StackTrace); + } + + return post; + } + + public void SetBoardInfo() + { + _logger.LogInformation("SetBoardInfo"); + string text = string.Empty; + + string url = $"https://www.ptt.cc/bbs/hotboards.html"; + MyWebClient client = new MyWebClient(); + client.Encoding = Encoding.UTF8; // 設定Webclient.Encoding + + string html = string.Empty; + try + { + html = client.DownloadString(url); + + List iteamList = new List(); + + HtmlDocument doc = new HtmlDocument(); + doc.LoadHtml(html); + HtmlDocument doctag = new HtmlDocument(); + var metaTags = doc.DocumentNode.SelectNodes("//div"); + if (metaTags != null) + { + foreach (var tag in metaTags) + { + + if (tag.Attributes["class"] != null) + { + if (tag.Attributes["class"].Value == "b-ent") + { + ////class="title" class="author" class="date" + doctag.LoadHtml(tag.OuterHtml); + Board Board = new Board(); + HtmlNode bodyNodes = doctag.DocumentNode.SelectSingleNode("//a[@class='board']"); + if (bodyNodes == null) continue; + Board.Href = bodyNodes.Attributes["href"].Value; + HtmlNode HDname = doctag.DocumentNode.SelectSingleNode("//div[@class='board-name']"); + Board.Name = HDname.InnerText; + HtmlNode HDnuser = doctag.DocumentNode.SelectSingleNode("//div[@class='board-nuser']"); + Board.Nuser = HDnuser.InnerText; + HtmlNode HDclass = doctag.DocumentNode.SelectSingleNode("//div[@class='board-class']"); + Board.Class = HDclass.InnerText; + HtmlNode HDtitle = doctag.DocumentNode.SelectSingleNode("//div[@class='board-title']"); + Board.Title = HDtitle.InnerText; + + if (!BContainer.dicBoardInfo.ContainsKey(Board.Name)) + BContainer.dicBoardInfo.Add(Board.Name, Board); + + BContainer.dicBoardInfo[Board.Name] = Board; + + } + + } + } + } + } + catch (Exception ex) + { + _logger.LogInformation($"SetBoardInfo[Exception]{ex.Message}"); + _logger.LogInformation($"SetBoardInfo[Exception]{ex.StackTrace}"); + } + + } + + private string GetPageNo(int page, int MaxPage) + { + string PageNo = ""; + + page = MaxPage - page + 1; + if ((page == 1) || (page < 1)) + { + return PageNo; + } + + PageNo = page.ToString(); + return PageNo; + } + + private int GetPageSize(string boardName) + { + string URL = $"https://www.ptt.cc/bbs/{boardName}/index.html"; + _logger.LogInformation(MethodBase.GetCurrentMethod().Name); + + try + { + var html = new MyWebClient().DownloadString(URL); + var doc = new HtmlDocument(); doc.LoadHtml(HttpUtility.HtmlDecode(html)); + var node = doc.DocumentNode.SelectSingleNode("//a[.='‹ 上頁']"); + var number = Regex.Replace(node.OuterHtml, "[^0-9]", ""); + + return int.Parse(number) + 1; + } + catch (Exception ex) + { + _logger.LogDebug($"{MethodBase.GetCurrentMethod().Name}[Exception]:{ex.Message}"); + _logger.LogDebug(ex.StackTrace); + } + + return 0; + } + + public class MyWebClient : WebClient + { + protected override WebRequest GetWebRequest(Uri uri) + { + WebRequest WR = base.GetWebRequest(uri); + WR.Timeout = 30 * 1000; + Cookie cookie = new Cookie("over18", "1", "/", "www.ptt.cc"); + + TryAddCookie(WR, cookie); + return WR; + } + + private static bool TryAddCookie(WebRequest webRequest, Cookie cookie) + { + HttpWebRequest httpRequest = webRequest as HttpWebRequest; + if (httpRequest == null) + { + return false; + } + + if (httpRequest.CookieContainer == null) + { + httpRequest.CookieContainer = new CookieContainer(); + } + + httpRequest.CookieContainer.Add(cookie); + return true; + } + + } + #endregion + + public RankByPost GetRank(string board, string aID) + { + string json = string.Empty; + RankByPost rankByPost = new RankByPost(); + try + { + var postRanks = _postRankRepository.Get().AsNoTracking() + .Where(x => x.Board == board && x.Aid == aID); + + rankByPost.Board = board; + rankByPost.AID = aID; + rankByPost.Goup = postRanks.Count(x => x.Rank == 1); + rankByPost.Down = postRanks.Count(x => x.Rank == -1); + } + catch (Exception ex) + { + json = string.Format($"{ex.Message}.{ex.InnerException?.Message}.{ex.StackTrace}"); + } + return rankByPost; + } + + public PostRank SetRank(string board, string aID, string pTTID, int iR) + { + string json = string.Empty; + PostRank postRank = null; + try + { + postRank = _postRankRepository.Get() + .Where(x => x.Board == board && x.Aid == aID && x.Pttid == pTTID) + .FirstOrDefault(); + if (postRank is null) + { + postRank = new PostRank() + { + No = Guid.NewGuid(), + Board = board.Trim(), + Aid = aID.Trim(), + Pttid = pTTID.Trim(), + Rank = iR + }; + _postRankRepository.Insert(postRank); + } + else + { + postRank.Rank = iR; + } + _postRankRepository.Save(); + } + catch (Exception ex) + { + json = string.Format("{0}.{1}.{2}", ex.Message, ex.InnerException.Message, ex.StackTrace); + } + return postRank; + } + } +} diff --git a/BILib/Repository/BoardInfoRepository.cs b/BILib/Repository/BoardInfoRepository.cs new file mode 100644 index 0000000..8ad9f3c --- /dev/null +++ b/BILib/Repository/BoardInfoRepository.cs @@ -0,0 +1,38 @@ +using DBModel.SqlModels; +using System; +using System.Linq; + +namespace BILib +{ + public class BoardInfoRepository : GenericRepository + { + public BoardInfoRepository(MWDBContext context) : base(context) + { + SetFakeData(); + } + + private void SetFakeData() + { +#if !DEBUG + return; +#endif + if (GetAsNoTracking().Any()) return; + + for (int i = 1; i <= 100; i++) + { + var newItem = new BoardInfo + { + Board = $"Test{i}", + ChineseDes = $"[Test{i}] 測試板{i}", + IsOpen = true, + OnlineUser = 10 * i, + Moderators = $"Ptter{i}", + LastUpdateTime = DateTime.UtcNow + }; + + Insert(newItem); + } + Save(); + } + } +} diff --git a/BILib/Repository/GenericRepository.cs b/BILib/Repository/GenericRepository.cs new file mode 100644 index 0000000..6b2b88e --- /dev/null +++ b/BILib/Repository/GenericRepository.cs @@ -0,0 +1,76 @@ +using DBModel.SqlModels; +using Microsoft.EntityFrameworkCore; +using System.Linq; + +namespace BILib +{ + /// + /// Ref: https://docs.microsoft.com/zh-tw/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application#create-a-generic-repository + /// + /// + public class GenericRepository where TEntity : class + { + private readonly MWDBContext _context; + private readonly DbSet _dbSet; + + public GenericRepository(MWDBContext context) + { + _context = context; + _dbSet = context.Set(); + } + + /// + /// 搜尋 (若後續須變更資料,請用此 API) + /// + /// + public virtual IQueryable Get() + { + return _dbSet; + } + + /// + /// 僅供不變更的單純搜尋;不追蹤 DB 資料變動,提高執行效能 + /// + /// + public virtual IQueryable GetAsNoTracking() + { + return _dbSet.AsNoTracking(); + } + + public virtual TEntity GetByID(object id) + { + return _dbSet.Find(id); + } + + public virtual void Insert(TEntity entity) + { + _dbSet.Add(entity); + } + + public virtual void Save() + { + _context.SaveChanges(); + } + + public virtual void Delete(object id) + { + TEntity entityToDelete = _dbSet.Find(id); + Delete(entityToDelete); + } + + public virtual void Delete(TEntity entityToDelete) + { + if (_context.Entry(entityToDelete).State == EntityState.Detached) + { + _dbSet.Attach(entityToDelete); + } + _dbSet.Remove(entityToDelete); + } + + public virtual void Update(TEntity entityToUpdate) + { + _dbSet.Attach(entityToUpdate); + _context.Entry(entityToUpdate).State = EntityState.Modified; + } + } +} diff --git a/BILib/Repository/PostRankRepository.cs b/BILib/Repository/PostRankRepository.cs new file mode 100644 index 0000000..50ebf37 --- /dev/null +++ b/BILib/Repository/PostRankRepository.cs @@ -0,0 +1,11 @@ +using DBModel.SqlModels; + +namespace BILib +{ + public class PostRankRepository : GenericRepository + { + public PostRankRepository(MWDBContext context) : base(context) + { + } + } +} diff --git a/DBModel/SqlModels/BoardInfo.cs b/DBModel/SqlModels/BoardInfo.cs index 93e96a2..f456c3d 100644 --- a/DBModel/SqlModels/BoardInfo.cs +++ b/DBModel/SqlModels/BoardInfo.cs @@ -1,10 +1,12 @@ using System; -using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; namespace DBModel.SqlModels { public partial class BoardInfo { + [Key] + public int Id { get; set; } public string Board { get; set; } public int? OnlineUser { get; set; } public string ChineseDes { get; set; } diff --git a/DBModel/SqlModels/MWDBContext.cs b/DBModel/SqlModels/MWDBContext.cs index 963cc89..927d50c 100644 --- a/DBModel/SqlModels/MWDBContext.cs +++ b/DBModel/SqlModels/MWDBContext.cs @@ -129,7 +129,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.HasNoKey(); + entity.HasKey(b => b.Id); entity.Property(e => e.Board) .IsRequired() diff --git a/middleware/Controllers/BoardController.cs b/middleware/Controllers/BoardController.cs index 6ac18d0..12552a6 100644 --- a/middleware/Controllers/BoardController.cs +++ b/middleware/Controllers/BoardController.cs @@ -1,13 +1,9 @@ -using System; +using BILib; +using DtoModel; +using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Threading.Tasks; -using BILib; -using DBModel.SqlModels; -using DtoModel; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; namespace middleware.Controllers { @@ -18,26 +14,19 @@ namespace middleware.Controllers [ApiController] public class BoardController : ControllerBase { - /// - /// Database context - /// - private readonly MWDBContext _context; - /// /// 看板商業邏輯 /// private readonly BoardBl _boardBl; - private readonly BILib.BoardHelper _boardHelper; + /// /// 建構子 /// - /// Database context - public BoardController(MWDBContext context) + /// + public BoardController(BoardBl boardBl) { - _context = context; - _boardBl = new BoardBl(_context); - _boardHelper = new BILib.BoardHelper(_context); + _boardBl = boardBl; } /// @@ -109,7 +98,7 @@ public ActionResult Get(string name) /// 結果清單 [Route("Search")] [HttpGet] - public ActionResult> Search(string keyword) + public ActionResult> Search([FromQuery] string keyword) { // 參數檢查 var validationResults = new List(); @@ -156,7 +145,7 @@ public ActionResult> Popular(int page = 1, int count = 20) return BadRequest(validationResults); } - return Ok(_boardHelper.GetPopularBoards().Skip((page - 1) * count).Take(count)); + return Ok(_boardBl.GetPopularBoards((page - 1) * count, count)); } /// diff --git a/middleware/NLog.config b/middleware/NLog.config new file mode 100644 index 0000000..c06c63c --- /dev/null +++ b/middleware/NLog.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/middleware/Program.cs b/middleware/Program.cs index a404e95..6fc129e 100644 --- a/middleware/Program.cs +++ b/middleware/Program.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; +using NLog.Web; namespace middleware { @@ -21,6 +16,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) => .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); - }); + }) + .UseNLog(); // NLog: Setup NLog for Dependency injection } } diff --git a/middleware/Startup.cs b/middleware/Startup.cs index 6cabfcf..82eb729 100644 --- a/middleware/Startup.cs +++ b/middleware/Startup.cs @@ -1,21 +1,19 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; +using BILib; using DBModel; using DBModel.SqlModels; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; namespace middleware { @@ -35,7 +33,12 @@ public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddSingleton(); - services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("MWDB"))); + services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("MWDB"))) + .AddScoped(); + + services.AddScoped() + .AddScoped(); + // Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(c => { From 91fe5bf947306ccdcd972edb72fbf45e048481de Mon Sep 17 00:00:00 2001 From: "tracyleecore@gmail.com" Date: Thu, 3 Dec 2020 15:25:44 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=AA=BF=E6=95=B4=20NLog=20=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E6=AA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware/NLog.config | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/middleware/NLog.config b/middleware/NLog.config index c06c63c..d0cd26b 100644 --- a/middleware/NLog.config +++ b/middleware/NLog.config @@ -3,13 +3,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwConfigExceptions="true"> + + + - - + + - + \ No newline at end of file