From ff708a1d945382b7b663cbe716963f09d8fe3792 Mon Sep 17 00:00:00 2001 From: linezero Date: Mon, 22 May 2017 12:36:38 +0800 Subject: [PATCH 1/7] Clean Architecture Model update Repository design pattern --- NetCoreBBS.sln | 25 +++++- src/ApplicationCore/ApplicationCore.csproj | 12 +++ src/ApplicationCore/Entities/BaseEntity.cs | 11 +++ src/ApplicationCore/Entities/Topic.cs | 36 ++++++++ src/ApplicationCore/Entities/TopicNode.cs | 17 ++++ src/ApplicationCore/Entities/TopicReply.cs | 18 ++++ src/ApplicationCore/Entities/User.cs | 21 +++++ .../Entities/UserCollection.cs | 16 ++++ src/ApplicationCore/Entities/UserMessage.cs | 19 +++++ src/ApplicationCore/Interfaces/IRepository.cs | 18 ++++ .../Interfaces/ITopicReplyRepository.cs | 8 ++ .../Interfaces/ITopicRepository.cs | 14 +++ src/ApplicationCore/Page.cs | 25 ++++++ src/Infrastructure/DataContext.cs | 34 ++++++++ src/Infrastructure/Infrastructure.csproj | 12 +++ src/Infrastructure/Repositorys/Repository.cs | 55 ++++++++++++ .../Repositorys/TopicReplyRepository.cs | 25 ++++++ .../Repositorys/TopicRepository.cs | 45 ++++++++++ .../Admin/Controllers/ManageController.cs | 2 +- .../Areas/Admin/Controllers/NodeController.cs | 3 +- .../Admin/Controllers/TopicController.cs | 15 ++-- .../Controllers/TopicRepliesController.cs | 2 +- .../Areas/Admin/Controllers/UserController.cs | 2 +- .../Areas/Admin/Views/Node/Create.cshtml | 2 +- .../Areas/Admin/Views/Node/Edit.cshtml | 2 +- .../Areas/Admin/Views/Node/Index.cshtml | 2 +- .../Areas/Admin/Views/Topic/Index.cshtml | 6 +- .../Areas/Admin/Views/User/Index.cshtml | 2 +- .../Areas/Admin/_ViewImports.cshtml | 2 +- .../Controllers/AccountController.cs | 2 +- src/NetCoreBBS/Controllers/HomeController.cs | 67 +++++++-------- src/NetCoreBBS/Controllers/TopicController.cs | 67 +++++++++------ src/NetCoreBBS/NetCoreBBS.csproj | 9 +- src/NetCoreBBS/Startup.cs | 9 +- src/NetCoreBBS/UserServices.cs | 2 +- src/NetCoreBBS/ViewComponents/Statistics.cs | 2 +- .../ViewComponents/TopicRankList.cs | 3 +- src/NetCoreBBS/ViewModels/TopicViewModel.cs | 4 +- src/NetCoreBBS/Views/Home/Index.cshtml | 85 +++++++++---------- src/NetCoreBBS/Views/Topic/Index.cshtml | 54 ++++++------ src/NetCoreBBS/Views/Topic/Node.cshtml | 62 +++++++------- src/NetCoreBBS/Views/_ViewImports.cshtml | 2 +- tests/UnitTests/UnitTests.csproj | 13 +++ 43 files changed, 633 insertions(+), 199 deletions(-) create mode 100644 src/ApplicationCore/ApplicationCore.csproj create mode 100644 src/ApplicationCore/Entities/BaseEntity.cs create mode 100644 src/ApplicationCore/Entities/Topic.cs create mode 100644 src/ApplicationCore/Entities/TopicNode.cs create mode 100644 src/ApplicationCore/Entities/TopicReply.cs create mode 100644 src/ApplicationCore/Entities/User.cs create mode 100644 src/ApplicationCore/Entities/UserCollection.cs create mode 100644 src/ApplicationCore/Entities/UserMessage.cs create mode 100644 src/ApplicationCore/Interfaces/IRepository.cs create mode 100644 src/ApplicationCore/Interfaces/ITopicReplyRepository.cs create mode 100644 src/ApplicationCore/Interfaces/ITopicRepository.cs create mode 100644 src/ApplicationCore/Page.cs create mode 100644 src/Infrastructure/DataContext.cs create mode 100644 src/Infrastructure/Infrastructure.csproj create mode 100644 src/Infrastructure/Repositorys/Repository.cs create mode 100644 src/Infrastructure/Repositorys/TopicReplyRepository.cs create mode 100644 src/Infrastructure/Repositorys/TopicRepository.cs create mode 100644 tests/UnitTests/UnitTests.csproj diff --git a/NetCoreBBS.sln b/NetCoreBBS.sln index 9e158e9..5b0d262 100644 --- a/NetCoreBBS.sln +++ b/NetCoreBBS.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +VisualStudioVersion = 15.0.26403.7 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{94F5C8A4-D158-4A10-AD26-C635A376CC92}" EndProject @@ -12,6 +12,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreBBS", "src\NetCoreBBS\NetCoreBBS.csproj", "{7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationCore", "src\ApplicationCore\ApplicationCore.csproj", "{65AC78E9-500F-42B5-954D-93F841F5D0F1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D25B2B42-A638-4F40-B51C-DCF41A3C8F4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests\UnitTests.csproj", "{152AAF50-21A3-477D-BB56-A25E56D4B611}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -22,11 +30,26 @@ Global {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Debug|Any CPU.Build.0 = Debug|Any CPU {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Release|Any CPU.Build.0 = Release|Any CPU + {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Release|Any CPU.Build.0 = Release|Any CPU + {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Release|Any CPU.Build.0 = Release|Any CPU + {152AAF50-21A3-477D-BB56-A25E56D4B611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {152AAF50-21A3-477D-BB56-A25E56D4B611}.Debug|Any CPU.Build.0 = Debug|Any CPU + {152AAF50-21A3-477D-BB56-A25E56D4B611}.Release|Any CPU.ActiveCfg = Release|Any CPU + {152AAF50-21A3-477D-BB56-A25E56D4B611}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D} = {94F5C8A4-D158-4A10-AD26-C635A376CC92} + {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7} = {94F5C8A4-D158-4A10-AD26-C635A376CC92} + {65AC78E9-500F-42B5-954D-93F841F5D0F1} = {94F5C8A4-D158-4A10-AD26-C635A376CC92} + {152AAF50-21A3-477D-BB56-A25E56D4B611} = {D25B2B42-A638-4F40-B51C-DCF41A3C8F4C} EndGlobalSection EndGlobal diff --git a/src/ApplicationCore/ApplicationCore.csproj b/src/ApplicationCore/ApplicationCore.csproj new file mode 100644 index 0000000..cdfd19f --- /dev/null +++ b/src/ApplicationCore/ApplicationCore.csproj @@ -0,0 +1,12 @@ + + + + netstandard1.4 + NetCoreBBS + + + + + + + \ No newline at end of file diff --git a/src/ApplicationCore/Entities/BaseEntity.cs b/src/ApplicationCore/Entities/BaseEntity.cs new file mode 100644 index 0000000..0ecea62 --- /dev/null +++ b/src/ApplicationCore/Entities/BaseEntity.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NetCoreBBS.Entities +{ + public class BaseEntity + { + public int Id { get; set; } + } +} diff --git a/src/ApplicationCore/Entities/Topic.cs b/src/ApplicationCore/Entities/Topic.cs new file mode 100644 index 0000000..2050191 --- /dev/null +++ b/src/ApplicationCore/Entities/Topic.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace NetCoreBBS.Entities +{ + public class Topic:BaseEntity + { + public int NodeId { get; set; } + public TopicNode Node { get; set; } + public string UserId { get; set; } + public User User { get; set; } + public string Email { get; set; } + public string Title { get; set; } + public string Content { get; set; } + /// + /// 置顶权重 + /// + public int Top { get; set; } + public TopicType Type { get; set; } + public int ViewCount { get; set; } + public int ReplyCount { get; set; } + public string LastReplyUserId { get; set; } + public User LastReplyUser { get; set; } + public DateTime LastReplyTime { get; set; } + public DateTime CreateOn { get; set; } + public virtual List Replys { get; set; } + } + public enum TopicType + { + Delete=0, + Normal = 1, + Top=2, + Good=3, + Hot=4 + } +} diff --git a/src/ApplicationCore/Entities/TopicNode.cs b/src/ApplicationCore/Entities/TopicNode.cs new file mode 100644 index 0000000..b14fd0d --- /dev/null +++ b/src/ApplicationCore/Entities/TopicNode.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace NetCoreBBS.Entities +{ + public class TopicNode:BaseEntity + { + public int ParentId { get; set; } + public string NodeName { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public int Order { get; set; } + public DateTime CreateOn { get; set; } + } +} diff --git a/src/ApplicationCore/Entities/TopicReply.cs b/src/ApplicationCore/Entities/TopicReply.cs new file mode 100644 index 0000000..fc6497c --- /dev/null +++ b/src/ApplicationCore/Entities/TopicReply.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace NetCoreBBS.Entities +{ + public class TopicReply:BaseEntity + { + public int TopicId { get; set; } + public string ReplyUserId { get; set; } + public User ReplyUser { get; set; } + public string ReplyEmail { get; set; } + public string ReplyContent { get; set; } + public DateTime CreateOn { get; set; } + } +} diff --git a/src/ApplicationCore/Entities/User.cs b/src/ApplicationCore/Entities/User.cs new file mode 100644 index 0000000..ab4d060 --- /dev/null +++ b/src/ApplicationCore/Entities/User.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; + +namespace NetCoreBBS.Entities +{ + public class User: IdentityUser + { + public string Avatar { get; set; } + public string Profile { get; set; } + public string Url { get; set; } + public string GitHub { get; set; } + public int TopicCount { get; set; } + public int TopicReplyCount { get; set; } + public int Score { get; set; } + public DateTime CreateOn { get; set; } + public DateTime LastTime { get; set; } + } +} diff --git a/src/ApplicationCore/Entities/UserCollection.cs b/src/ApplicationCore/Entities/UserCollection.cs new file mode 100644 index 0000000..a66ffbf --- /dev/null +++ b/src/ApplicationCore/Entities/UserCollection.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace NetCoreBBS.Entities +{ + public class UserCollection:BaseEntity + { + public string UserId { get; set; } + public int TopicId { get; set; } + public Topic Topic { get; set; } + public int State { get; set; } + public DateTime CreateOn { get; set; } + } +} diff --git a/src/ApplicationCore/Entities/UserMessage.cs b/src/ApplicationCore/Entities/UserMessage.cs new file mode 100644 index 0000000..db87b48 --- /dev/null +++ b/src/ApplicationCore/Entities/UserMessage.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace NetCoreBBS.Entities +{ + public class UserMessage:BaseEntity + { + public string SendUserId { get; set; } + public User SendUser { get; set; } + public string ReceiveUserId { get; set; } + public User ReceiveUser { get; set; } + public string Type { get; set; } + public string Content { get; set; } + public int State { get; set; } + public DateTime CreateOn { get; set; } + } +} diff --git a/src/ApplicationCore/Interfaces/IRepository.cs b/src/ApplicationCore/Interfaces/IRepository.cs new file mode 100644 index 0000000..618d8b0 --- /dev/null +++ b/src/ApplicationCore/Interfaces/IRepository.cs @@ -0,0 +1,18 @@ +using NetCoreBBS.Entities; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; + +namespace NetCoreBBS.Interfaces +{ + public interface IRepository where T: BaseEntity + { + T GetById(int id); + IEnumerable List(); + IEnumerable List(Expression> predicate); + void Add(T entity); + void Delete(T entity); + void Edit(T entity); + } +} diff --git a/src/ApplicationCore/Interfaces/ITopicReplyRepository.cs b/src/ApplicationCore/Interfaces/ITopicReplyRepository.cs new file mode 100644 index 0000000..b81defa --- /dev/null +++ b/src/ApplicationCore/Interfaces/ITopicReplyRepository.cs @@ -0,0 +1,8 @@ +using NetCoreBBS.Entities; + +namespace NetCoreBBS.Interfaces +{ + public interface ITopicReplyRepository:IRepository + { + } +} diff --git a/src/ApplicationCore/Interfaces/ITopicRepository.cs b/src/ApplicationCore/Interfaces/ITopicRepository.cs new file mode 100644 index 0000000..e4916d6 --- /dev/null +++ b/src/ApplicationCore/Interfaces/ITopicRepository.cs @@ -0,0 +1,14 @@ +using NetCoreBBS.Entities; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; + +namespace NetCoreBBS.Interfaces +{ + public interface ITopicRepository:IRepository + { + Page PageList(int pagesize,int pageindex); + Page PageList(Expression> predicate, int pagesize, int pageindex); + } +} diff --git a/src/ApplicationCore/Page.cs b/src/ApplicationCore/Page.cs new file mode 100644 index 0000000..740a2e6 --- /dev/null +++ b/src/ApplicationCore/Page.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NetCoreBBS.Entities +{ + public class Page + where T : class + { + public int Total { get; private set; } + public int PageSize { get; private set; } + public List List { get; private set; } + public Page(List list, int pageSize, int total) + { + this.List = list; + this.PageSize = pageSize; + this.Total = total; + } + + public int GetPageCount() + { + return (Total + PageSize - 1) / PageSize; + } + } +} diff --git a/src/Infrastructure/DataContext.cs b/src/Infrastructure/DataContext.cs new file mode 100644 index 0000000..aa3d2d3 --- /dev/null +++ b/src/Infrastructure/DataContext.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using NetCoreBBS.Entities; + +namespace NetCoreBBS.Infrastructure +{ + public class DataContext : IdentityDbContext + { + public DataContext(DbContextOptions options) + : base(options) + { + } + public DbSet Topics { get; set; } + public DbSet TopicReplys { get; set; } + public DbSet TopicNodes { get; set; } + public DbSet UserMessages { get; set; } + public DbSet UserTopics { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Entity().ToTable("Topic"); + modelBuilder.Entity().ToTable("TopicReply"); + modelBuilder.Entity().ToTable("TopicNode"); + modelBuilder.Entity().ToTable("User"); + modelBuilder.Entity().ToTable("UserMessage"); + modelBuilder.Entity().ToTable("UserCollection"); + } + } +} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj new file mode 100644 index 0000000..8174a0e --- /dev/null +++ b/src/Infrastructure/Infrastructure.csproj @@ -0,0 +1,12 @@ + + + + netstandard1.4 + NetCoreBBS.Infrastructure + + + + + + + \ No newline at end of file diff --git a/src/Infrastructure/Repositorys/Repository.cs b/src/Infrastructure/Repositorys/Repository.cs new file mode 100644 index 0000000..68e86e5 --- /dev/null +++ b/src/Infrastructure/Repositorys/Repository.cs @@ -0,0 +1,55 @@ +using Microsoft.EntityFrameworkCore; +using NetCoreBBS.Entities; +using NetCoreBBS.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NetCoreBBS.Infrastructure.Repositorys +{ + public class Repository : IRepository where T : BaseEntity + { + private readonly DataContext _dbContext; + + public Repository(DataContext dbContext) + { + _dbContext = dbContext; + } + + public virtual T GetById(int id) + { + return _dbContext.Set().Find(id); + } + + public virtual IEnumerable List() + { + return _dbContext.Set().AsEnumerable(); + } + + public virtual IEnumerable List(System.Linq.Expressions.Expression> predicate) + { + return _dbContext.Set() + .Where(predicate) + .AsEnumerable(); + } + + public void Add(T entity) + { + _dbContext.Set().Add(entity); + _dbContext.SaveChanges(); + } + + public void Edit(T entity) + { + _dbContext.Entry(entity).State = EntityState.Modified; + _dbContext.SaveChanges(); + } + + public void Delete(T entity) + { + _dbContext.Set().Remove(entity); + _dbContext.SaveChanges(); + } + } +} diff --git a/src/Infrastructure/Repositorys/TopicReplyRepository.cs b/src/Infrastructure/Repositorys/TopicReplyRepository.cs new file mode 100644 index 0000000..049ff5b --- /dev/null +++ b/src/Infrastructure/Repositorys/TopicReplyRepository.cs @@ -0,0 +1,25 @@ +using NetCoreBBS.Entities; +using NetCoreBBS.Interfaces; +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; +using System.Linq; + +namespace NetCoreBBS.Infrastructure.Repositorys +{ + public class TopicReplyRepository : Repository, ITopicReplyRepository + { + private readonly DataContext _dbContext; + public TopicReplyRepository(DataContext dbContext) : base(dbContext) + { + _dbContext = dbContext; + } + + public override IEnumerable List(Expression> predicate) + { + return _dbContext.TopicReplys.Include(r=>r.ReplyUser).Where(predicate); + } + } +} diff --git a/src/Infrastructure/Repositorys/TopicRepository.cs b/src/Infrastructure/Repositorys/TopicRepository.cs new file mode 100644 index 0000000..8c3532d --- /dev/null +++ b/src/Infrastructure/Repositorys/TopicRepository.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NetCoreBBS.Entities; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using NetCoreBBS.Interfaces; + +namespace NetCoreBBS.Infrastructure.Repositorys +{ + public class TopicRepository : Repository,ITopicRepository + { + private readonly DataContext _dbContext; + + public TopicRepository(DataContext dbContext) + :base(dbContext) + { + _dbContext = dbContext; + } + public override Topic GetById(int id) + { + return _dbContext.Topics.Include(r => r.User).Include(r => r.Node).Include(r => r.LastReplyUser).FirstOrDefault(r => r.Id == id); + } + + public Page PageList(int pagesize=20, int pageindex=1) + { + return PageList(null, pagesize, pageindex); + } + + public Page PageList(Expression> predicate, int pagesize=20, int pageindex=1) + { + var topics = _dbContext.Topics.Include(r=>r.User).Include(r=>r.Node).Include(r=>r.LastReplyUser).AsQueryable(); + if (predicate != null) + { + topics=topics.Where(predicate); + } + var count = topics.Count(); + topics = topics.OrderByDescending(r => r.CreateOn) + .OrderByDescending(r => r.Top) + .Skip((pageindex - 1) * pagesize).Take(pagesize); + return new Page(topics.ToList(), pagesize, count); + } + } +} diff --git a/src/NetCoreBBS/Areas/Admin/Controllers/ManageController.cs b/src/NetCoreBBS/Areas/Admin/Controllers/ManageController.cs index fc643ba..38ab260 100644 --- a/src/NetCoreBBS/Areas/Admin/Controllers/ManageController.cs +++ b/src/NetCoreBBS/Areas/Admin/Controllers/ManageController.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 diff --git a/src/NetCoreBBS/Areas/Admin/Controllers/NodeController.cs b/src/NetCoreBBS/Areas/Admin/Controllers/NodeController.cs index 1eb61fa..030aed4 100644 --- a/src/NetCoreBBS/Areas/Admin/Controllers/NodeController.cs +++ b/src/NetCoreBBS/Areas/Admin/Controllers/NodeController.cs @@ -4,7 +4,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using NetCoreBBS.Models; +using NetCoreBBS.Entities; +using NetCoreBBS.Infrastructure; using Microsoft.AspNetCore.Authorization; namespace NetCoreBBS.Areas.Admin.Controllers diff --git a/src/NetCoreBBS/Areas/Admin/Controllers/TopicController.cs b/src/NetCoreBBS/Areas/Admin/Controllers/TopicController.cs index 53e2260..fc36d01 100644 --- a/src/NetCoreBBS/Areas/Admin/Controllers/TopicController.cs +++ b/src/NetCoreBBS/Areas/Admin/Controllers/TopicController.cs @@ -4,7 +4,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; +using NetCoreBBS.Entities; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 @@ -72,15 +73,15 @@ public IActionResult Update(int id, string type) case "top": topic.Top = 1; break; - case "good": - topic.Good = true; - break; + //case "good": + // topic.Good = true; + // break; case "notop": topic.Top = 0; break; - case "nogood": - topic.Good = false; - break; + //case "nogood": + // topic.Good = false; + // break; } _context.Update(topic); _context.SaveChanges(); diff --git a/src/NetCoreBBS/Areas/Admin/Controllers/TopicRepliesController.cs b/src/NetCoreBBS/Areas/Admin/Controllers/TopicRepliesController.cs index 94d3e02..4d6b88a 100644 --- a/src/NetCoreBBS/Areas/Admin/Controllers/TopicRepliesController.cs +++ b/src/NetCoreBBS/Areas/Admin/Controllers/TopicRepliesController.cs @@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; using Microsoft.AspNetCore.Authorization; namespace NetCoreBBS.Areas.Admin.Controllers diff --git a/src/NetCoreBBS/Areas/Admin/Controllers/UserController.cs b/src/NetCoreBBS/Areas/Admin/Controllers/UserController.cs index 5de48a3..aaa0420 100644 --- a/src/NetCoreBBS/Areas/Admin/Controllers/UserController.cs +++ b/src/NetCoreBBS/Areas/Admin/Controllers/UserController.cs @@ -4,8 +4,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using NetCoreBBS.Models; using Microsoft.AspNetCore.Authorization; +using NetCoreBBS.Infrastructure; namespace NetCoreBBS.Areas.Admin.Controllers { diff --git a/src/NetCoreBBS/Areas/Admin/Views/Node/Create.cshtml b/src/NetCoreBBS/Areas/Admin/Views/Node/Create.cshtml index bffb4d2..9561cee 100644 --- a/src/NetCoreBBS/Areas/Admin/Views/Node/Create.cshtml +++ b/src/NetCoreBBS/Areas/Admin/Views/Node/Create.cshtml @@ -1,4 +1,4 @@ -@model NetCoreBBS.Models.TopicNode +@model TopicNode @{ ViewData["Title"] = "新增节点"; diff --git a/src/NetCoreBBS/Areas/Admin/Views/Node/Edit.cshtml b/src/NetCoreBBS/Areas/Admin/Views/Node/Edit.cshtml index ec90551..7bd1712 100644 --- a/src/NetCoreBBS/Areas/Admin/Views/Node/Edit.cshtml +++ b/src/NetCoreBBS/Areas/Admin/Views/Node/Edit.cshtml @@ -1,4 +1,4 @@ -@model NetCoreBBS.Models.TopicNode +@model TopicNode @{ ViewData["Title"] = "Edit"; diff --git a/src/NetCoreBBS/Areas/Admin/Views/Node/Index.cshtml b/src/NetCoreBBS/Areas/Admin/Views/Node/Index.cshtml index fa0c195..d21ac83 100644 --- a/src/NetCoreBBS/Areas/Admin/Views/Node/Index.cshtml +++ b/src/NetCoreBBS/Areas/Admin/Views/Node/Index.cshtml @@ -1,4 +1,4 @@ -@model IEnumerable +@model IEnumerable @{ ViewData["Title"] = "节点管理"; diff --git a/src/NetCoreBBS/Areas/Admin/Views/Topic/Index.cshtml b/src/NetCoreBBS/Areas/Admin/Views/Topic/Index.cshtml index c4f829c..39ff5a0 100644 --- a/src/NetCoreBBS/Areas/Admin/Views/Topic/Index.cshtml +++ b/src/NetCoreBBS/Areas/Admin/Views/Topic/Index.cshtml @@ -12,7 +12,7 @@ 发布时间 回复数 回复时间 - 优质 + 类型 回复 管理 @@ -25,7 +25,7 @@ @item.CreateOn @item.ReplyCount @item.LastReplyTime - @(item.Good ? "是" : "否") + @(item.Type) @if (item.ReplyCount > 0) { @@ -71,7 +71,7 @@ 取消置顶 } | - @if (!item.Good) + @if ((int)item.Type==1) { 优质 } diff --git a/src/NetCoreBBS/Areas/Admin/Views/User/Index.cshtml b/src/NetCoreBBS/Areas/Admin/Views/User/Index.cshtml index 97e94eb..836791f 100644 --- a/src/NetCoreBBS/Areas/Admin/Views/User/Index.cshtml +++ b/src/NetCoreBBS/Areas/Admin/Views/User/Index.cshtml @@ -1,4 +1,4 @@ -@model IEnumerable +@model IEnumerable @{ ViewData["Title"] = "用户管理"; diff --git a/src/NetCoreBBS/Areas/Admin/_ViewImports.cshtml b/src/NetCoreBBS/Areas/Admin/_ViewImports.cshtml index e29997a..4c643ff 100644 --- a/src/NetCoreBBS/Areas/Admin/_ViewImports.cshtml +++ b/src/NetCoreBBS/Areas/Admin/_ViewImports.cshtml @@ -1,5 +1,5 @@ @using NetCoreBBS -@using NetCoreBBS.Models +@using NetCoreBBS.Entities @using NetCoreBBS.ViewModels @using Microsoft.AspNetCore.Identity @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/NetCoreBBS/Controllers/AccountController.cs b/src/NetCoreBBS/Controllers/AccountController.cs index 468b7fb..791a9d7 100644 --- a/src/NetCoreBBS/Controllers/AccountController.cs +++ b/src/NetCoreBBS/Controllers/AccountController.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Identity; -using NetCoreBBS.Models; +using NetCoreBBS.Entities; using NetCoreBBS.ViewModels; using Microsoft.Extensions.Logging; using System.Security.Claims; diff --git a/src/NetCoreBBS/Controllers/HomeController.cs b/src/NetCoreBBS/Controllers/HomeController.cs index 3d3fdb1..9b54ae1 100644 --- a/src/NetCoreBBS/Controllers/HomeController.cs +++ b/src/NetCoreBBS/Controllers/HomeController.cs @@ -1,64 +1,55 @@ using System; using System.Linq; using Microsoft.AspNetCore.Mvc; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; using NetCoreBBS.ViewModels; using Microsoft.AspNetCore.Mvc.Rendering; +using NetCoreBBS.Entities; +using NetCoreBBS.Interfaces; namespace NetCoreBBS.Controllers { public class HomeController : Controller { - private DataContext _context; + private ITopicRepository _topic; + private IRepository _node; public UserManager UserManager { get; } - - public HomeController(DataContext context, UserManager userManager) + public HomeController(ITopicRepository topic, IRepository node, UserManager userManager) { - _context = context; + _topic = topic; + _node = node; UserManager = userManager; } public IActionResult Index([FromServices]IUserServices user) { var pagesize = 20; var pageindex = 1; - var topics = _context.Topics - .GroupJoin(_context.TopicNodes, - r => r.NodeId, - n => n.Id, - (r, n) => new { r = r, n = n }) - .SelectMany(result => result.n.DefaultIfEmpty(), (r, n) => new TopicViewModel - { - Id = r.r.Id, - NodeId = r.r.NodeId, - NodeName = n == null ? "" : n.Name, - Email = r.r.Email, - Title = r.r.Title, - Top = r.r.Top, - Good = r.r.Good, - ReplyCount = r.r.ReplyCount, - LastReplyTime = r.r.LastReplyTime, - CreateOn = r.r.CreateOn - }).AsQueryable(); + Page result = null ; if (!string.IsNullOrEmpty(Request.Query["page"])) pageindex = Convert.ToInt32(Request.Query["page"]); if (!string.IsNullOrEmpty(Request.Query["s"])) - topics = topics.Where(r => r.Title.Contains(Request.Query["s"])); - var count = topics.Count(); - //var q = from t in topics - // join n in _context.TopicNodes on t.NodeId equals n.Id into tn - // from n2 in tn.DefaultIfEmpty() - // select t; - ViewBag.Topics = topics - .OrderByDescending(r => r.CreateOn) - .OrderByDescending(r => r.Top) - .Skip(pagesize * (pageindex - 1)) - .Take(pagesize).ToList(); + result = _topic.PageList(r => r.Title.Contains(Request.Query["s"]), pagesize, pageindex); + else + result = _topic.PageList(pagesize, pageindex); + ViewBag.Topics = result.List.Select(r=>new TopicViewModel + { + Id = r.Id, + NodeId = r.Node.Id, + NodeName = r.Node.Name, + UserName = r.User.UserName, + Title = r.Title, + Top = r.Top, + Type=r.Type, + ReplyCount = r.ReplyCount, + LastReplyTime = r.LastReplyTime, + CreateOn = r.CreateOn + }).ToList(); ViewBag.PageIndex = pageindex; - ViewBag.PageCount = count % pagesize == 0 ? count / pagesize : count / pagesize + 1; + ViewBag.PageCount = result.GetPageCount(); ViewBag.User = user.User.Result; - var nodes = _context.TopicNodes.ToList(); + var nodes = _node.List().ToList(); ViewBag.Nodes = nodes; ViewBag.NodeListItem = nodes.Where(r => r.ParentId != 0).Select(r => new SelectListItem { Value = r.Id.ToString(), Text = r.Name }); return View(); @@ -71,8 +62,8 @@ public IActionResult Index(Topic topic) if (ModelState.IsValid) { topic.CreateOn = DateTime.Now; - _context.Topics.Add(topic); - _context.SaveChanges(); + topic.Type = TopicType.Normal; + _topic.Add(topic); } return RedirectToAction("Index"); } diff --git a/src/NetCoreBBS/Controllers/TopicController.cs b/src/NetCoreBBS/Controllers/TopicController.cs index 01c43ed..70955b2 100644 --- a/src/NetCoreBBS/Controllers/TopicController.cs +++ b/src/NetCoreBBS/Controllers/TopicController.cs @@ -3,7 +3,10 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; +using NetCoreBBS.Entities; +using NetCoreBBS.Interfaces; +using NetCoreBBS.ViewModels; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 @@ -11,39 +14,42 @@ namespace NetCoreBBS.Controllers { public class TopicController : Controller { - private DataContext _context; - public TopicController(DataContext context) + private ITopicRepository _topic; + private IRepository _node; + private ITopicReplyRepository _reply; + public TopicController(ITopicRepository topic, IRepository node, ITopicReplyRepository reply) { - _context = context; + _topic = topic; + _node = node; + _reply = reply; } // GET: /Topic/1 [Route("/Topic/{id}")] public IActionResult Index(int id) { if (id <= 0) return Redirect("/"); - var topic = _context.Topics.FirstOrDefault(r => r.Id == id); + var topic = _topic.GetById(id); if (topic == null) return Redirect("/"); - var replys = _context.TopicReplys.Where(r => r.TopicId == id).ToList(); + var replys = _reply.List(r => r.TopicId == id).ToList(); topic.ViewCount += 1; - _context.SaveChanges(); + _topic.Edit(topic); ViewBag.Replys = replys; return View(topic); } [HttpPost] [ValidateAntiForgeryToken] [Route("/Topic/{id}")] - public IActionResult Index(TopicReply reply) + public IActionResult Index([Bind("TopicId,ReplyUserId,ReplyEmail,ReplyContent")]TopicReply reply) { - if (ModelState.IsValid) + if (ModelState.IsValid&&!string.IsNullOrEmpty(reply.ReplyContent)) { - reply.Id = 0; reply.CreateOn = DateTime.Now; - _context.TopicReplys.Add(reply); - var topic = _context.Topics.Single(r => r.Id == reply.TopicId); - topic.LastReplyUserId = reply.UserId; + _reply.Add(reply); + var topic = _topic.GetById(reply.TopicId); + topic.LastReplyUserId = reply.ReplyUserId; topic.LastReplyTime = reply.CreateOn; topic.ReplyCount += 1; - _context.SaveChanges(); + _topic.Edit(topic); } return RedirectToAction("Index", "Topic", new { Id = reply.TopicId }); } @@ -52,27 +58,36 @@ public IActionResult Index(TopicReply reply) public IActionResult Node(string name) { if (string.IsNullOrEmpty(name)) return Redirect("/"); - var node = _context.TopicNodes.FirstOrDefault(r => r.NodeName == name); + var node = _node.List(r => r.NodeName == name).FirstOrDefault(); if (node == null) - node= _context.TopicNodes.FirstOrDefault(r => r.Id == Convert.ToInt32(name)); + node= _node.GetById(Convert.ToInt32(name)); if (node == null) return Redirect("/"); var pagesize = 20; var pageindex = 1; - var topics = _context.Topics.Where(r => r.NodeId == node.Id).AsQueryable(); + Page result; if (!string.IsNullOrEmpty(Request.Query["page"])) pageindex = Convert.ToInt32(Request.Query["page"]); if (!string.IsNullOrEmpty(Request.Query["s"])) - topics = topics.Where(r => r.Title.Contains(Request.Query["s"])); - var count = topics.Count(); - ViewBag.Topics = topics - .OrderByDescending(r => r.CreateOn) - .OrderByDescending(r => r.Top) - .Skip(pagesize * (pageindex - 1)) - .Take(pagesize).ToList(); + result = _topic.PageList(r => r.NodeId == node.Id && r.Title.Contains(Request.Query["s"]),pagesize,pageindex); + else + result = _topic.PageList(r => r.NodeId == node.Id, pagesize, pageindex); + ViewBag.Topics = result.List.Select(r => new TopicViewModel + { + Id = r.Id, + NodeId = r.Node.Id, + NodeName = r.Node.Name, + UserName = r.User.UserName, + Title = r.Title, + Top = r.Top, + Type = r.Type, + ReplyCount = r.ReplyCount, + LastReplyTime = r.LastReplyTime, + CreateOn = r.CreateOn + }).ToList(); ViewBag.PageIndex = pageindex; - ViewBag.PageCount = count % pagesize == 0 ? count / pagesize : count / pagesize + 1; + ViewBag.PageCount = result.GetPageCount(); ViewBag.Node = node; - ViewBag.Count = count; + ViewBag.Count = result.Total; return View(); } } diff --git a/src/NetCoreBBS/NetCoreBBS.csproj b/src/NetCoreBBS/NetCoreBBS.csproj index e9fa103..121c610 100644 --- a/src/NetCoreBBS/NetCoreBBS.csproj +++ b/src/NetCoreBBS/NetCoreBBS.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 @@ -31,7 +31,7 @@ - + @@ -51,4 +51,9 @@ + + + + + diff --git a/src/NetCoreBBS/Startup.cs b/src/NetCoreBBS/Startup.cs index 886f7bb..c7b84f9 100644 --- a/src/NetCoreBBS/Startup.cs +++ b/src/NetCoreBBS/Startup.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; using Microsoft.EntityFrameworkCore; using NLog.Extensions.Logging; using NetCoreBBS.Middleware; @@ -16,6 +16,9 @@ using Microsoft.Extensions.WebEncoders; using System.Text.Unicode; using System.Text.Encodings.Web; +using NetCoreBBS.Entities; +using NetCoreBBS.Infrastructure.Repositorys; +using NetCoreBBS.Interfaces; namespace NetCoreBBS { @@ -45,7 +48,9 @@ public void ConfigureServices(IServiceCollection services) }).AddEntityFrameworkStores().AddDefaultTokenProviders(); // Add framework services. services.AddMvc(); - + services.AddSingleton, Repository>(); + services.AddSingleton(); + services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddMemoryCache(); diff --git a/src/NetCoreBBS/UserServices.cs b/src/NetCoreBBS/UserServices.cs index adbd8eb..b1d12d7 100644 --- a/src/NetCoreBBS/UserServices.cs +++ b/src/NetCoreBBS/UserServices.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using NetCoreBBS.Models; +using NetCoreBBS.Entities; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Http; diff --git a/src/NetCoreBBS/ViewComponents/Statistics.cs b/src/NetCoreBBS/ViewComponents/Statistics.cs index d3d17d0..9130126 100644 --- a/src/NetCoreBBS/ViewComponents/Statistics.cs +++ b/src/NetCoreBBS/ViewComponents/Statistics.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; -using NetCoreBBS.Models; +using NetCoreBBS.Infrastructure; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/NetCoreBBS/ViewComponents/TopicRankList.cs b/src/NetCoreBBS/ViewComponents/TopicRankList.cs index f85b521..9094538 100644 --- a/src/NetCoreBBS/ViewComponents/TopicRankList.cs +++ b/src/NetCoreBBS/ViewComponents/TopicRankList.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using NetCoreBBS.Models; using Microsoft.Extensions.Caching.Memory; +using NetCoreBBS.Infrastructure; +using NetCoreBBS.Entities; namespace NetCoreBBS.ViewComponents { diff --git a/src/NetCoreBBS/ViewModels/TopicViewModel.cs b/src/NetCoreBBS/ViewModels/TopicViewModel.cs index 67f8da8..93c06a3 100644 --- a/src/NetCoreBBS/ViewModels/TopicViewModel.cs +++ b/src/NetCoreBBS/ViewModels/TopicViewModel.cs @@ -10,10 +10,10 @@ public class TopicViewModel public int Id { get; set; } public int NodeId { get; set; } public string NodeName { get; set; } - public string Email { get; set; } + public string UserName { get; set; } public string Title { get; set; } public int Top { get; set; } - public bool Good { get; set; } + public Entities.TopicType Type { get; set; } public int ReplyCount { get; set; } public DateTime LastReplyTime { get; set; } public DateTime CreateOn { get; set; } diff --git a/src/NetCoreBBS/Views/Home/Index.cshtml b/src/NetCoreBBS/Views/Home/Index.cshtml index 511f8a0..3c23c9a 100644 --- a/src/NetCoreBBS/Views/Home/Index.cshtml +++ b/src/NetCoreBBS/Views/Home/Index.cshtml @@ -5,7 +5,6 @@ var nodes = ViewBag.Nodes as List; } @model Topic -
@@ -28,72 +27,70 @@
- @item.NodeName】发布于 @item.CreateOn.ToString("MM-dd HH:mm") + @item.NodeName】发布于 @item.CreateOn.ToString("MM-dd HH:mm") @if (item.LastReplyTime != DateTime.MinValue) - { + { - } + }
@if (item.ReplyCount > 0) - { + { @item.ReplyCount - } + }
} +
-
-
- -
- + @if (user != null) + { + +
+ +
+ +
-
-
- @if (user == null) - { - +
+
- +
- } - else - { - - - } -
-
- -
-
-
-
- -
- +
+ +
+ +
-
-
-
- +
+ + +
+ +
-
- + + } + else + { + 发布新话题 +

需要登录发布新话题, + 如果你还没有账号请点击这里 注册

+ }
讨论节点分类导航
@@ -104,7 +101,7 @@
- @foreach (var n in nodes.Where(r => r.ParentId == item.Id).OrderBy(r=>r.Order)) + @foreach (var n in nodes.Where(r => r.ParentId == item.Id).OrderBy(r => r.Order)) { @n.Name } diff --git a/src/NetCoreBBS/Views/Topic/Index.cshtml b/src/NetCoreBBS/Views/Topic/Index.cshtml index 1c2cc8f..178d9fc 100644 --- a/src/NetCoreBBS/Views/Topic/Index.cshtml +++ b/src/NetCoreBBS/Views/Topic/Index.cshtml @@ -12,9 +12,9 @@

@(Model.Top == 1 ? "[置顶]" : "")@Model.Title

- node + @Model.Node.Name · - @Model.Email + @Model.User.UserName · 于 @Model.CreateOn.ToString("MM-dd HH:mm")发布 · @@ -31,7 +31,7 @@
-

回复:

+

共收到 @list.Count 条回复:

@for (int i = 0; i < list.Count; i++) @@ -46,7 +46,7 @@
- @item.ReplyEmail + @item.ReplyUser.UserName · #@(i + 1) · @item.CreateOn.ToString("MM-dd HH:mm") @@ -66,34 +66,32 @@
-
- -
- @if (user == null) - { - + @if (user != null) + { + + + + +
+
- +
- } - else - { - - - } -
-
- -
-
-
-
-
- +
+
+ +
-
- + + } + else + { +

+ 需要登录发表回复, + 如果你还没有账号请点击这里 注册。 +

+ }
diff --git a/src/NetCoreBBS/Views/Topic/Node.cshtml b/src/NetCoreBBS/Views/Topic/Node.cshtml index 8b83cc4..4c1e036 100644 --- a/src/NetCoreBBS/Views/Topic/Node.cshtml +++ b/src/NetCoreBBS/Views/Topic/Node.cshtml @@ -1,8 +1,8 @@ @inject UserServices services @{ var node = ViewBag.Node as TopicNode; - ViewData["Title"] = node.Name+"-.NET Core 跨平台论坛"; - var list = ViewBag.Topics as List; + ViewData["Title"] = node.Name + "-.NET Core 跨平台论坛"; + var list = ViewBag.Topics as List; var user = await services.User; } @model Topic @@ -34,7 +34,7 @@
- @node.Name】发布于 @item.CreateOn.ToString("MM-dd HH:mm") + @node.Name】发布于 @item.CreateOn.ToString("MM-dd HH:mm") @if (item.LastReplyTime != DateTime.MinValue) { @@ -55,40 +55,38 @@
-
- -
- @if (user == null) - { - + @if (user != null) + { + + +
+
- +
- } - else - { - - - } -
-
- -
-
-
-
- -
- +
+ +
+ +
-
-
-
- +
+ + +
+ +
-
- + + } + else + { +

+ 需要登录发布新话题, + 如果你还没有账号请点击这里 注册。 +

+ }
diff --git a/src/NetCoreBBS/Views/_ViewImports.cshtml b/src/NetCoreBBS/Views/_ViewImports.cshtml index e29997a..4c643ff 100644 --- a/src/NetCoreBBS/Views/_ViewImports.cshtml +++ b/src/NetCoreBBS/Views/_ViewImports.cshtml @@ -1,5 +1,5 @@ @using NetCoreBBS -@using NetCoreBBS.Models +@using NetCoreBBS.Entities @using NetCoreBBS.ViewModels @using Microsoft.AspNetCore.Identity @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/tests/UnitTests/UnitTests.csproj b/tests/UnitTests/UnitTests.csproj new file mode 100644 index 0000000..f032596 --- /dev/null +++ b/tests/UnitTests/UnitTests.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp1.1 + + + + + + + + + From 9fc2c15f56c5a6bf4c652c2efba252f03063ea2a Mon Sep 17 00:00:00 2001 From: linezero Date: Mon, 22 May 2017 13:49:52 +0800 Subject: [PATCH 2/7] Update README.md --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fcd60b9..fef1308 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,23 @@ # NETCoreBBS ASP.NET Core Light forum NETCoreBBS -ASP.NET Core 1.0 + EF Core 1.0 Sqlite + Bootstrap +ASP.NET Core + EF Core Sqlite + Bootstrap .NET Core 跨平台轻论坛 -[live demo](http://104.251.232.80/) +[live demo](http://dotnet.link/) +## 开发 + +1. `git clone https://github.com/linezero/NETCoreBBS.git` +2. 使用 Visual Studio 2017 打开 `NetCoreBBS.sln` +3. 点击 `调试->开始调试` 即可运行起来,或者直接点击工具栏上的`NetCoreBBS`即可。 + +注意:默认为80端口,可能会和本地端口冲突,可以到Program.cs 中更改 `.UseUrls("http://*:80")`,然后更改启动URL既可。 + + +## 功能 -## 已开发 1. 节点功能 1. 主题发布 2. 主题回复 From ace9934c7001afdd2401fcfaaf428d5630036291 Mon Sep 17 00:00:00 2001 From: linezero Date: Mon, 22 May 2017 14:46:30 +0800 Subject: [PATCH 3/7] Models Delete --- src/NetCoreBBS/Models/DataContext.cs | 33 --------------------------- src/NetCoreBBS/Models/Topic.cs | 34 ---------------------------- src/NetCoreBBS/Models/TopicNode.cs | 18 --------------- src/NetCoreBBS/Models/TopicReply.cs | 20 ---------------- src/NetCoreBBS/Models/User.cs | 21 ----------------- src/NetCoreBBS/Models/UserMessage.cs | 18 --------------- src/NetCoreBBS/Models/UserTopic.cs | 15 ------------ 7 files changed, 159 deletions(-) delete mode 100644 src/NetCoreBBS/Models/DataContext.cs delete mode 100644 src/NetCoreBBS/Models/Topic.cs delete mode 100644 src/NetCoreBBS/Models/TopicNode.cs delete mode 100644 src/NetCoreBBS/Models/TopicReply.cs delete mode 100644 src/NetCoreBBS/Models/User.cs delete mode 100644 src/NetCoreBBS/Models/UserMessage.cs delete mode 100644 src/NetCoreBBS/Models/UserTopic.cs diff --git a/src/NetCoreBBS/Models/DataContext.cs b/src/NetCoreBBS/Models/DataContext.cs deleted file mode 100644 index a9a6e6c..0000000 --- a/src/NetCoreBBS/Models/DataContext.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace NetCoreBBS.Models -{ - public class DataContext : IdentityDbContext - { - public DataContext(DbContextOptions options) - : base(options) - { - } - public DbSet Topics { get; set; } - public DbSet TopicReplys { get; set; } - public DbSet TopicNodes { get; set; } - public DbSet UserMessages { get; set; } - public DbSet UserTopics { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - modelBuilder.Entity().ToTable("Topic"); - modelBuilder.Entity().ToTable("TopicReply"); - modelBuilder.Entity().ToTable("TopicNode"); - modelBuilder.Entity().ToTable("User"); - modelBuilder.Entity().ToTable("UserMessage"); - modelBuilder.Entity().ToTable("UserTopic"); - } - } -} diff --git a/src/NetCoreBBS/Models/Topic.cs b/src/NetCoreBBS/Models/Topic.cs deleted file mode 100644 index 1755cf0..0000000 --- a/src/NetCoreBBS/Models/Topic.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace NetCoreBBS.Models -{ - public class Topic - { - public int Id { get; set; } - public int NodeId { get; set; } - public Guid UserId { get; set; } - [Required] - public string Email { get; set; } - [Required] - public string Title { get; set; } - [Required] - public string Content { get; set; } - /// - /// 置顶权重 - /// - public int Top { get; set; } - /// - /// 精华 - /// - public bool Good { get; set; } - public int ViewCount { get; set; } - public int ReplyCount { get; set; } - public Guid LastReplyUserId { get; set; } - public DateTime LastReplyTime { get; set; } - public DateTime CreateOn { get; set; } - } -} diff --git a/src/NetCoreBBS/Models/TopicNode.cs b/src/NetCoreBBS/Models/TopicNode.cs deleted file mode 100644 index 8af6865..0000000 --- a/src/NetCoreBBS/Models/TopicNode.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace NetCoreBBS.Models -{ - public class TopicNode - { - public int Id { get; set; } - public int ParentId { get; set; } - public string NodeName { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public int Order { get; set; } - public DateTime CreateOn { get; set; } - } -} diff --git a/src/NetCoreBBS/Models/TopicReply.cs b/src/NetCoreBBS/Models/TopicReply.cs deleted file mode 100644 index 64a3d5a..0000000 --- a/src/NetCoreBBS/Models/TopicReply.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace NetCoreBBS.Models -{ - public class TopicReply - { - public int Id { get; set; } - public int TopicId { get; set; } - public Guid UserId { get; set; } - [Required] - public string ReplyEmail { get; set; } - [Required] - public string ReplyContent { get; set; } - public DateTime CreateOn { get; set; } - } -} diff --git a/src/NetCoreBBS/Models/User.cs b/src/NetCoreBBS/Models/User.cs deleted file mode 100644 index c63e6ba..0000000 --- a/src/NetCoreBBS/Models/User.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; - -namespace NetCoreBBS.Models -{ - public class User: IdentityUser - { - public string Avatar { get; set; } - public string Profile { get; set; } - public string Url { get; set; } - public string GitHub { get; set; } - public int TopicCount { get; set; } - public int TopicReplyCount { get; set; } - public int Score { get; set; } - public DateTime CreateOn { get; set; } - public DateTime LastTime { get; set; } - } -} diff --git a/src/NetCoreBBS/Models/UserMessage.cs b/src/NetCoreBBS/Models/UserMessage.cs deleted file mode 100644 index c9517d4..0000000 --- a/src/NetCoreBBS/Models/UserMessage.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace NetCoreBBS.Models -{ - public class UserMessage - { - public int Id { get; set; } - public Guid SendUserId { get; set; } - public Guid ReceiveUserId { get; set; } - public string Type { get; set; } - public string Content { get; set; } - public bool IsRead { get; set; } - public DateTime CreateOn { get; set; } - } -} diff --git a/src/NetCoreBBS/Models/UserTopic.cs b/src/NetCoreBBS/Models/UserTopic.cs deleted file mode 100644 index ec2f42e..0000000 --- a/src/NetCoreBBS/Models/UserTopic.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace NetCoreBBS.Models -{ - public class UserTopic - { - public int Id { get; set; } - public Guid UserId { get; set; } - public int TopicId { get; set; } - public DateTime CreateOn { get; set; } - } -} From e2a1b0af72ba702bc34aeeb1f57a32bc1af1fe42 Mon Sep 17 00:00:00 2001 From: linezero Date: Tue, 6 Jun 2017 10:54:16 +0800 Subject: [PATCH 4/7] dotnet ef #8 dotnet ef migrations add InitMigration --startup-project ../NetCoreBBS/NetCoreBBS.csproj --- src/Infrastructure/Infrastructure.csproj | 5 + .../20170606024516_InitMigration.Designer.cs | 412 +++++++++++++++++ .../20170606024516_InitMigration.cs | 417 ++++++++++++++++++ .../Migrations/DataContextModelSnapshot.cs | 411 +++++++++++++++++ src/NetCoreBBS/NetCoreBBS.csproj | 2 - 5 files changed, 1245 insertions(+), 2 deletions(-) create mode 100644 src/Infrastructure/Migrations/20170606024516_InitMigration.Designer.cs create mode 100644 src/Infrastructure/Migrations/20170606024516_InitMigration.cs create mode 100644 src/Infrastructure/Migrations/DataContextModelSnapshot.cs diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 8174a0e..66cdb87 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -9,4 +9,9 @@ + + + + + \ No newline at end of file diff --git a/src/Infrastructure/Migrations/20170606024516_InitMigration.Designer.cs b/src/Infrastructure/Migrations/20170606024516_InitMigration.Designer.cs new file mode 100644 index 0000000..2af5659 --- /dev/null +++ b/src/Infrastructure/Migrations/20170606024516_InitMigration.Designer.cs @@ -0,0 +1,412 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using NetCoreBBS.Infrastructure; +using NetCoreBBS.Entities; + +namespace NetCoreBBS.Infrastructure.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20170606024516_InitMigration")] + partial class InitMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.Topic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("CreateOn"); + + b.Property("Email"); + + b.Property("LastReplyTime"); + + b.Property("LastReplyUserId"); + + b.Property("NodeId"); + + b.Property("ReplyCount"); + + b.Property("Title"); + + b.Property("Top"); + + b.Property("Type"); + + b.Property("UserId"); + + b.Property("ViewCount"); + + b.HasKey("Id"); + + b.HasIndex("LastReplyUserId"); + + b.HasIndex("NodeId"); + + b.HasIndex("UserId"); + + b.ToTable("Topic"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.TopicNode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateOn"); + + b.Property("Description"); + + b.Property("Name"); + + b.Property("NodeName"); + + b.Property("Order"); + + b.Property("ParentId"); + + b.HasKey("Id"); + + b.ToTable("TopicNode"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.TopicReply", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateOn"); + + b.Property("ReplyContent"); + + b.Property("ReplyEmail"); + + b.Property("ReplyUserId"); + + b.Property("TopicId"); + + b.HasKey("Id"); + + b.HasIndex("ReplyUserId"); + + b.HasIndex("TopicId"); + + b.ToTable("TopicReply"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Avatar"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("CreateOn"); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("GitHub"); + + b.Property("LastTime"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("Profile"); + + b.Property("Score"); + + b.Property("SecurityStamp"); + + b.Property("TopicCount"); + + b.Property("TopicReplyCount"); + + b.Property("TwoFactorEnabled"); + + b.Property("Url"); + + b.Property("UserName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateOn"); + + b.Property("State"); + + b.Property("TopicId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("TopicId"); + + b.ToTable("UserCollection"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("CreateOn"); + + b.Property("ReceiveUserId"); + + b.Property("SendUserId"); + + b.Property("State"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("ReceiveUserId"); + + b.HasIndex("SendUserId"); + + b.ToTable("UserMessage"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.HasOne("NetCoreBBS.Entities.User") + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.HasOne("NetCoreBBS.Entities.User") + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany("Users") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("NetCoreBBS.Entities.User") + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.Topic", b => + { + b.HasOne("NetCoreBBS.Entities.User", "LastReplyUser") + .WithMany() + .HasForeignKey("LastReplyUserId"); + + b.HasOne("NetCoreBBS.Entities.TopicNode", "Node") + .WithMany() + .HasForeignKey("NodeId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("NetCoreBBS.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.TopicReply", b => + { + b.HasOne("NetCoreBBS.Entities.User", "ReplyUser") + .WithMany() + .HasForeignKey("ReplyUserId"); + + b.HasOne("NetCoreBBS.Entities.Topic") + .WithMany("Replys") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserCollection", b => + { + b.HasOne("NetCoreBBS.Entities.Topic", "Topic") + .WithMany() + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserMessage", b => + { + b.HasOne("NetCoreBBS.Entities.User", "ReceiveUser") + .WithMany() + .HasForeignKey("ReceiveUserId"); + + b.HasOne("NetCoreBBS.Entities.User", "SendUser") + .WithMany() + .HasForeignKey("SendUserId"); + }); + } + } +} diff --git a/src/Infrastructure/Migrations/20170606024516_InitMigration.cs b/src/Infrastructure/Migrations/20170606024516_InitMigration.cs new file mode 100644 index 0000000..88a9f0c --- /dev/null +++ b/src/Infrastructure/Migrations/20170606024516_InitMigration.cs @@ -0,0 +1,417 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NetCoreBBS.Infrastructure.Migrations +{ + public partial class InitMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(nullable: false), + ConcurrencyStamp = table.Column(nullable: true), + Name = table.Column(maxLength: 256, nullable: true), + NormalizedName = table.Column(maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(nullable: false), + LoginProvider = table.Column(nullable: false), + Name = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + }); + + migrationBuilder.CreateTable( + name: "TopicNode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreateOn = table.Column(nullable: false), + Description = table.Column(nullable: true), + Name = table.Column(nullable: true), + NodeName = table.Column(nullable: true), + Order = table.Column(nullable: false), + ParentId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TopicNode", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "User", + columns: table => new + { + Id = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + Avatar = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + CreateOn = table.Column(nullable: false), + Email = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + GitHub = table.Column(nullable: true), + LastTime = table.Column(nullable: false), + LockoutEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + PasswordHash = table.Column(nullable: true), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + Profile = table.Column(nullable: true), + Score = table.Column(nullable: false), + SecurityStamp = table.Column(nullable: true), + TopicCount = table.Column(nullable: false), + TopicReplyCount = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + Url = table.Column(nullable: true), + UserName = table.Column(maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_User", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(nullable: false), + ProviderKey = table.Column(nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(nullable: false), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Topic", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Content = table.Column(nullable: true), + CreateOn = table.Column(nullable: false), + Email = table.Column(nullable: true), + LastReplyTime = table.Column(nullable: false), + LastReplyUserId = table.Column(nullable: true), + NodeId = table.Column(nullable: false), + ReplyCount = table.Column(nullable: false), + Title = table.Column(nullable: true), + Top = table.Column(nullable: false), + Type = table.Column(nullable: false), + UserId = table.Column(nullable: true), + ViewCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Topic", x => x.Id); + table.ForeignKey( + name: "FK_Topic_User_LastReplyUserId", + column: x => x.LastReplyUserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Topic_TopicNode_NodeId", + column: x => x.NodeId, + principalTable: "TopicNode", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Topic_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "UserMessage", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Content = table.Column(nullable: true), + CreateOn = table.Column(nullable: false), + ReceiveUserId = table.Column(nullable: true), + SendUserId = table.Column(nullable: true), + State = table.Column(nullable: false), + Type = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserMessage", x => x.Id); + table.ForeignKey( + name: "FK_UserMessage_User_ReceiveUserId", + column: x => x.ReceiveUserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_UserMessage_User_SendUserId", + column: x => x.SendUserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "TopicReply", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreateOn = table.Column(nullable: false), + ReplyContent = table.Column(nullable: true), + ReplyEmail = table.Column(nullable: true), + ReplyUserId = table.Column(nullable: true), + TopicId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TopicReply", x => x.Id); + table.ForeignKey( + name: "FK_TopicReply_User_ReplyUserId", + column: x => x.ReplyUserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_TopicReply_Topic_TopicId", + column: x => x.TopicId, + principalTable: "Topic", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserCollection", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreateOn = table.Column(nullable: false), + State = table.Column(nullable: false), + TopicId = table.Column(nullable: false), + UserId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserCollection", x => x.Id); + table.ForeignKey( + name: "FK_UserCollection_Topic_TopicId", + column: x => x.TopicId, + principalTable: "Topic", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_Topic_LastReplyUserId", + table: "Topic", + column: "LastReplyUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Topic_NodeId", + table: "Topic", + column: "NodeId"); + + migrationBuilder.CreateIndex( + name: "IX_Topic_UserId", + table: "Topic", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_TopicReply_ReplyUserId", + table: "TopicReply", + column: "ReplyUserId"); + + migrationBuilder.CreateIndex( + name: "IX_TopicReply_TopicId", + table: "TopicReply", + column: "TopicId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "User", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "User", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_UserCollection_TopicId", + table: "UserCollection", + column: "TopicId"); + + migrationBuilder.CreateIndex( + name: "IX_UserMessage_ReceiveUserId", + table: "UserMessage", + column: "ReceiveUserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserMessage_SendUserId", + table: "UserMessage", + column: "SendUserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "TopicReply"); + + migrationBuilder.DropTable( + name: "UserCollection"); + + migrationBuilder.DropTable( + name: "UserMessage"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "Topic"); + + migrationBuilder.DropTable( + name: "User"); + + migrationBuilder.DropTable( + name: "TopicNode"); + } + } +} diff --git a/src/Infrastructure/Migrations/DataContextModelSnapshot.cs b/src/Infrastructure/Migrations/DataContextModelSnapshot.cs new file mode 100644 index 0000000..6708b8b --- /dev/null +++ b/src/Infrastructure/Migrations/DataContextModelSnapshot.cs @@ -0,0 +1,411 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using NetCoreBBS.Infrastructure; +using NetCoreBBS.Entities; + +namespace NetCoreBBS.Infrastructure.Migrations +{ + [DbContext(typeof(DataContext))] + partial class DataContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.Topic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("CreateOn"); + + b.Property("Email"); + + b.Property("LastReplyTime"); + + b.Property("LastReplyUserId"); + + b.Property("NodeId"); + + b.Property("ReplyCount"); + + b.Property("Title"); + + b.Property("Top"); + + b.Property("Type"); + + b.Property("UserId"); + + b.Property("ViewCount"); + + b.HasKey("Id"); + + b.HasIndex("LastReplyUserId"); + + b.HasIndex("NodeId"); + + b.HasIndex("UserId"); + + b.ToTable("Topic"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.TopicNode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateOn"); + + b.Property("Description"); + + b.Property("Name"); + + b.Property("NodeName"); + + b.Property("Order"); + + b.Property("ParentId"); + + b.HasKey("Id"); + + b.ToTable("TopicNode"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.TopicReply", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateOn"); + + b.Property("ReplyContent"); + + b.Property("ReplyEmail"); + + b.Property("ReplyUserId"); + + b.Property("TopicId"); + + b.HasKey("Id"); + + b.HasIndex("ReplyUserId"); + + b.HasIndex("TopicId"); + + b.ToTable("TopicReply"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Avatar"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("CreateOn"); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("GitHub"); + + b.Property("LastTime"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("Profile"); + + b.Property("Score"); + + b.Property("SecurityStamp"); + + b.Property("TopicCount"); + + b.Property("TopicReplyCount"); + + b.Property("TwoFactorEnabled"); + + b.Property("Url"); + + b.Property("UserName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateOn"); + + b.Property("State"); + + b.Property("TopicId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("TopicId"); + + b.ToTable("UserCollection"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("CreateOn"); + + b.Property("ReceiveUserId"); + + b.Property("SendUserId"); + + b.Property("State"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("ReceiveUserId"); + + b.HasIndex("SendUserId"); + + b.ToTable("UserMessage"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.HasOne("NetCoreBBS.Entities.User") + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.HasOne("NetCoreBBS.Entities.User") + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany("Users") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("NetCoreBBS.Entities.User") + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.Topic", b => + { + b.HasOne("NetCoreBBS.Entities.User", "LastReplyUser") + .WithMany() + .HasForeignKey("LastReplyUserId"); + + b.HasOne("NetCoreBBS.Entities.TopicNode", "Node") + .WithMany() + .HasForeignKey("NodeId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("NetCoreBBS.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.TopicReply", b => + { + b.HasOne("NetCoreBBS.Entities.User", "ReplyUser") + .WithMany() + .HasForeignKey("ReplyUserId"); + + b.HasOne("NetCoreBBS.Entities.Topic") + .WithMany("Replys") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserCollection", b => + { + b.HasOne("NetCoreBBS.Entities.Topic", "Topic") + .WithMany() + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NetCoreBBS.Entities.UserMessage", b => + { + b.HasOne("NetCoreBBS.Entities.User", "ReceiveUser") + .WithMany() + .HasForeignKey("ReceiveUserId"); + + b.HasOne("NetCoreBBS.Entities.User", "SendUser") + .WithMany() + .HasForeignKey("SendUserId"); + }); + } + } +} diff --git a/src/NetCoreBBS/NetCoreBBS.csproj b/src/NetCoreBBS/NetCoreBBS.csproj index 121c610..f1d17e6 100644 --- a/src/NetCoreBBS/NetCoreBBS.csproj +++ b/src/NetCoreBBS/NetCoreBBS.csproj @@ -29,7 +29,6 @@ - @@ -47,7 +46,6 @@ - From 0e1aca08da0f2ed87522122b39e66ec7934b3e86 Mon Sep 17 00:00:00 2001 From: linezero Date: Tue, 6 Jun 2017 11:17:26 +0800 Subject: [PATCH 5/7] Add Nodes #7 --- src/NetCoreBBS/Startup.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/NetCoreBBS/Startup.cs b/src/NetCoreBBS/Startup.cs index c7b84f9..86afb14 100644 --- a/src/NetCoreBBS/Startup.cs +++ b/src/NetCoreBBS/Startup.cs @@ -102,8 +102,23 @@ private void InitializeNetCoreBBSDatabase(IServiceProvider serviceProvider) using (var serviceScope = serviceProvider.GetRequiredService().CreateScope()) { var db = serviceScope.ServiceProvider.GetService(); - db.Database.EnsureCreated(); + db.Database.Migrate(); + if (db.TopicNodes.Count() == 0) + { + db.TopicNodes.AddRange(GetTopicNodes()); + db.SaveChanges(); + } } } + + IEnumerable GetTopicNodes() + { + return new List() + { + new TopicNode() { Name=".NET Core", NodeName="netcore", ParentId=0, Order=1, CreateOn=DateTime.Now, }, + new TopicNode() { Name=".NET Core", NodeName="netcore", ParentId=1, Order=1, CreateOn=DateTime.Now, }, + new TopicNode() { Name="ASP.NET Core", NodeName="aspnetcore", ParentId=1, Order=1, CreateOn=DateTime.Now, } + }; + } } } From 93ddbec35ceccff3e08f7921b6e53fd5f3f30fe7 Mon Sep 17 00:00:00 2001 From: linezero Date: Fri, 9 Jun 2017 08:43:40 +0800 Subject: [PATCH 6/7] User Info add user center --- .../Repositorys/TopicRepository.cs | 6 +- src/NetCoreBBS/Controllers/HomeController.cs | 1 + src/NetCoreBBS/Controllers/TopicController.cs | 1 + src/NetCoreBBS/Controllers/UserController.cs | 79 +++++++++++++++ src/NetCoreBBS/NetCoreBBS.csproj | 4 + src/NetCoreBBS/ViewModels/TopicViewModel.cs | 1 + src/NetCoreBBS/ViewModels/UserViewModel.cs | 17 ++++ src/NetCoreBBS/Views/Home/Index.cshtml | 8 +- .../Views/Shared/_LoginPartial.cshtml | 21 ++-- src/NetCoreBBS/Views/Topic/Index.cshtml | 5 +- src/NetCoreBBS/Views/Topic/Node.cshtml | 2 +- src/NetCoreBBS/Views/User/Edit.cshtml | 51 ++++++++++ src/NetCoreBBS/Views/User/Index.cshtml | 99 +++++++++++++++++++ src/NetCoreBBS/wwwroot/css/site.css | 22 ++++- 14 files changed, 299 insertions(+), 18 deletions(-) create mode 100644 src/NetCoreBBS/Controllers/UserController.cs create mode 100644 src/NetCoreBBS/ViewModels/UserViewModel.cs create mode 100644 src/NetCoreBBS/Views/User/Edit.cshtml create mode 100644 src/NetCoreBBS/Views/User/Index.cshtml diff --git a/src/Infrastructure/Repositorys/TopicRepository.cs b/src/Infrastructure/Repositorys/TopicRepository.cs index 8c3532d..e354889 100644 --- a/src/Infrastructure/Repositorys/TopicRepository.cs +++ b/src/Infrastructure/Repositorys/TopicRepository.cs @@ -22,6 +22,10 @@ public override Topic GetById(int id) { return _dbContext.Topics.Include(r => r.User).Include(r => r.Node).Include(r => r.LastReplyUser).FirstOrDefault(r => r.Id == id); } + public override IEnumerable List(Expression> predicate) + { + return _dbContext.Topics.Include(r => r.Node).Where(predicate); + } public Page PageList(int pagesize=20, int pageindex=1) { @@ -30,7 +34,7 @@ public Page PageList(int pagesize=20, int pageindex=1) public Page PageList(Expression> predicate, int pagesize=20, int pageindex=1) { - var topics = _dbContext.Topics.Include(r=>r.User).Include(r=>r.Node).Include(r=>r.LastReplyUser).AsQueryable(); + var topics = _dbContext.Topics.Include(r=>r.User).Include(r=>r.Node).Include(r=>r.LastReplyUser).AsQueryable().AsNoTracking(); if (predicate != null) { topics=topics.Where(predicate); diff --git a/src/NetCoreBBS/Controllers/HomeController.cs b/src/NetCoreBBS/Controllers/HomeController.cs index 9b54ae1..641ac26 100644 --- a/src/NetCoreBBS/Controllers/HomeController.cs +++ b/src/NetCoreBBS/Controllers/HomeController.cs @@ -39,6 +39,7 @@ public IActionResult Index([FromServices]IUserServices user) NodeId = r.Node.Id, NodeName = r.Node.Name, UserName = r.User.UserName, + Avatar=r.User.Avatar, Title = r.Title, Top = r.Top, Type=r.Type, diff --git a/src/NetCoreBBS/Controllers/TopicController.cs b/src/NetCoreBBS/Controllers/TopicController.cs index 70955b2..260ce6c 100644 --- a/src/NetCoreBBS/Controllers/TopicController.cs +++ b/src/NetCoreBBS/Controllers/TopicController.cs @@ -77,6 +77,7 @@ public IActionResult Node(string name) NodeId = r.Node.Id, NodeName = r.Node.Name, UserName = r.User.UserName, + Avatar=r.User.Avatar, Title = r.Title, Top = r.Top, Type = r.Type, diff --git a/src/NetCoreBBS/Controllers/UserController.cs b/src/NetCoreBBS/Controllers/UserController.cs new file mode 100644 index 0000000..9ba4c0d --- /dev/null +++ b/src/NetCoreBBS/Controllers/UserController.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using NetCoreBBS.Interfaces; +using NetCoreBBS.Entities; +using Microsoft.AspNetCore.Authorization; +using NetCoreBBS.ViewModels; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Hosting; +using System.IO; + +namespace NetCoreBBS.Controllers +{ + [Authorize] + public class UserController : Controller + { + private ITopicRepository _topic; + private ITopicReplyRepository _reply; + private UserManager UserManager; + private IHostingEnvironment _env; + public UserController(ITopicRepository topic, ITopicReplyRepository reply, UserManager userManager, IHostingEnvironment env) + { + _topic = topic; + _reply = reply; + UserManager = userManager; + _env = env; + } + public IActionResult Index() + { + var u = UserManager.GetUserAsync(User).Result; + var topics = _topic.List(r => r.UserId == u.Id).ToList(); + var replys = _reply.List(r => r.ReplyUserId == u.Id).ToList(); + ViewBag.Topics = topics; + ViewBag.Replys = replys; + return View(u); + } + + public IActionResult Edit() + { + return View(UserManager.GetUserAsync(User).Result); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Edit(UserViewModel usermodel) + { + var user = UserManager.GetUserAsync(User).Result; + if (ModelState.IsValid) + { + if (usermodel.Avatar != null) + { + var avatar = usermodel.Avatar; + if (avatar.Length / 1024 > 100) + { + return Content("ͷļС100KB"); + } + var ext = Path.GetExtension(avatar.FileName); + var avatarpath = Path.Combine("images", "avatar", user.Id + ext); + var filepath = Path.Combine(_env.WebRootPath, avatarpath); + using (FileStream fs = new FileStream(filepath, FileMode.Create)) + { + avatar.CopyTo(fs); + fs.Flush(); + } + user.Avatar = avatarpath; + } + user.Email = usermodel.Email; + user.Url = usermodel.Url; + user.GitHub = usermodel.GitHub; + user.Profile = usermodel.Profile; + await UserManager.UpdateAsync(user); + return RedirectToAction("Index"); + } + return View(user); + } + } +} \ No newline at end of file diff --git a/src/NetCoreBBS/NetCoreBBS.csproj b/src/NetCoreBBS/NetCoreBBS.csproj index f1d17e6..b9bace0 100644 --- a/src/NetCoreBBS/NetCoreBBS.csproj +++ b/src/NetCoreBBS/NetCoreBBS.csproj @@ -54,4 +54,8 @@ + + + + diff --git a/src/NetCoreBBS/ViewModels/TopicViewModel.cs b/src/NetCoreBBS/ViewModels/TopicViewModel.cs index 93c06a3..c3edaa0 100644 --- a/src/NetCoreBBS/ViewModels/TopicViewModel.cs +++ b/src/NetCoreBBS/ViewModels/TopicViewModel.cs @@ -11,6 +11,7 @@ public class TopicViewModel public int NodeId { get; set; } public string NodeName { get; set; } public string UserName { get; set; } + public string Avatar { get; set; } public string Title { get; set; } public int Top { get; set; } public Entities.TopicType Type { get; set; } diff --git a/src/NetCoreBBS/ViewModels/UserViewModel.cs b/src/NetCoreBBS/ViewModels/UserViewModel.cs new file mode 100644 index 0000000..9d47e97 --- /dev/null +++ b/src/NetCoreBBS/ViewModels/UserViewModel.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace NetCoreBBS.ViewModels +{ + public class UserViewModel + { + public string Email { get; set; } + public IFormFile Avatar { get; set; } + public string Profile { get; set; } + public string Url { get; set; } + public string GitHub { get; set; } + } +} diff --git a/src/NetCoreBBS/Views/Home/Index.cshtml b/src/NetCoreBBS/Views/Home/Index.cshtml index 3c23c9a..6294c10 100644 --- a/src/NetCoreBBS/Views/Home/Index.cshtml +++ b/src/NetCoreBBS/Views/Home/Index.cshtml @@ -22,7 +22,7 @@ {
- 96 + 96
@@ -31,7 +31,7 @@
- @item.NodeName】发布于 @item.CreateOn.ToString("MM-dd HH:mm") + @item.NodeName   发布于 @item.CreateOn.ToString("MM-dd HH:mm") @if (item.LastReplyTime != DateTime.MinValue) { @@ -87,9 +87,7 @@ } else { - 发布新话题 -

需要登录发布新话题, - 如果你还没有账号请点击这里 注册

+ 发布新话题 }
diff --git a/src/NetCoreBBS/Views/Shared/_LoginPartial.cshtml b/src/NetCoreBBS/Views/Shared/_LoginPartial.cshtml index b19b7d3..64282d9 100644 --- a/src/NetCoreBBS/Views/Shared/_LoginPartial.cshtml +++ b/src/NetCoreBBS/Views/Shared/_LoginPartial.cshtml @@ -6,13 +6,20 @@
- +
@@ -40,7 +40,7 @@
@@ -53,7 +53,6 @@ -
diff --git a/src/NetCoreBBS/Views/Topic/Node.cshtml b/src/NetCoreBBS/Views/Topic/Node.cshtml index 4c1e036..84ff883 100644 --- a/src/NetCoreBBS/Views/Topic/Node.cshtml +++ b/src/NetCoreBBS/Views/Topic/Node.cshtml @@ -25,7 +25,7 @@ {
- 96 + 96
diff --git a/src/NetCoreBBS/Views/User/Edit.cshtml b/src/NetCoreBBS/Views/User/Edit.cshtml new file mode 100644 index 0000000..bbf5bb8 --- /dev/null +++ b/src/NetCoreBBS/Views/User/Edit.cshtml @@ -0,0 +1,51 @@ +@model User +@{ + ViewData["Title"] = "Edit"; +} + +

修改个人信息

+ + +
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+ \ No newline at end of file diff --git a/src/NetCoreBBS/Views/User/Index.cshtml b/src/NetCoreBBS/Views/User/Index.cshtml new file mode 100644 index 0000000..4ce8c6b --- /dev/null +++ b/src/NetCoreBBS/Views/User/Index.cshtml @@ -0,0 +1,99 @@ +@model User +@{ + ViewData["Title"] = "个人主页"; + var topics = ViewBag.Topics as List; + var replys = ViewBag.Replys as List; +} + +
+
+ +
+
+ +
+
+
+ +
+
+
+
+
    + @foreach (var item in replys) + { +
  • +
    + @item.ReplyContent + at @(DateTime.Now.Subtract(item.CreateOn).Days) 天前 +
    +
  • + } +
+
+
+
+
+ @Model.Profile +
+
+
+
+
+
+
diff --git a/src/NetCoreBBS/wwwroot/css/site.css b/src/NetCoreBBS/wwwroot/css/site.css index 618e870..b8235da 100644 --- a/src/NetCoreBBS/wwwroot/css/site.css +++ b/src/NetCoreBBS/wwwroot/css/site.css @@ -41,11 +41,12 @@ .avatar-48 { height:48px; width:48px; + max-width:48px; border-radius:120px; } .title{font-size:18px;margin-bottom:0px;margin-top:0px;} .title a{line-height:28px;} -.info{color:#ABA8A6;margin-bottom:0px;margin-top:0px;} +.info{color:#ABA8A6;margin-bottom:0px;margin-top:0px;font-size:13px;} .node-list .node{margin-bottom:10px;margin-top:0px;} .node-list .node .media-left{min-width:130px;font-weight:normal;text-align:right;color:#aaa;float:left;} .node-list .node .name {margin-bottom:10px;width:100px;display:block;float:left;text-align:left;} @@ -65,4 +66,23 @@ .pagination{margin:0px;} img { max-width:100%;height:auto; +} +.avatar-96 { + height: 96px; + width: 96px; + border-radius: 120px; +} + +.recent-topics ul li .title, +.recent-replies ul li .title { + font-size: 14px; +} + +.recent-topics ul li .info { + font-size: 12px; +} + +.recent-topics ul li .node { + color: #777; + margin-right: 3px; } \ No newline at end of file From d28390cdef226196fda5db025152441b9aeca739 Mon Sep 17 00:00:00 2001 From: linezero Date: Tue, 18 Jul 2017 16:43:22 +0800 Subject: [PATCH 7/7] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fef1308..93d3c6d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ASP.NET Core + EF Core Sqlite + Bootstrap .NET Core 跨平台轻论坛 -[live demo](http://dotnet.link/) +[使用技术点介绍](http://www.cnblogs.com/linezero/p/NETCoreBBS.html) ## 开发 @@ -25,6 +25,7 @@ ASP.NET Core + EF Core Sqlite + Bootstrap 3. 用户登录注册 4. 主题置顶 5. 后台管理 +6. 个人中心 ## License NETCoreBBS is licensed under [MIT](LICENSE).