篇(18)-Asp.Net Core入门实战-文章管理之文章内容管理(下拉框二级结构递归) ...

打印 上一主题 下一主题

主题 622|帖子 622|积分 1866

篇(18)-Asp.Net Core入门实战-文章管理之文章内容管理(下拉框二级结构递归实现)
文章管理是CMS系统的核心表之一,存储文章内容,特点就是字段端,属性多,比如是否标识为热点、推荐等属性,是否发布,类别,SEO关键字等。我们本章讲解文章内容的增删改查。
(1).文章Sql表结构设计
  1. CREATE TABLE [dbo].[Article](
  2. [Id] [int] IDENTITY(1,1) NOT NULL,
  3. [CategoryId] [int] NOT NULL,
  4. [Title] [varchar](128) NOT NULL,
  5. [ImageUrl] [varchar](128) NULL,
  6. [Content] [text] NULL,
  7. [ViewCount] [int] NOT NULL,
  8. [Sort] [int] NOT NULL,
  9. [Author] [varchar](64) NULL,
  10. [Source] [varchar](128) NULL,
  11. [SeoTitle] [varchar](128) NULL,
  12. [SeoKeyword] [varchar](256) NULL,
  13. [SeoDescription] [varchar](512) NULL,
  14. [AddManagerId] [int] NOT NULL,
  15. [AddTime] [datetime] NOT NULL,
  16. [ModifyManagerId] [int] NULL,
  17. [ModifyTime] [datetime] NULL,
  18. [IsTop] [bit] NOT NULL,
  19. [IsSlide] [bit] NOT NULL,
  20. [IsRed] [bit] NOT NULL,
  21. [IsPublish] [bit] NOT NULL,
  22. [IsDeleted] [bit] NOT NULL,
  23. CONSTRAINT [PK_ARTICLE] PRIMARY KEY NONCLUSTERED
  24. (
  25. [Id] ASC
  26. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  27. ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  28. GO
  29. SET ANSI_PADDING OFF
  30. GO
  31. ALTER TABLE [dbo].[Article] ADD DEFAULT (getdate()) FOR [AddTime]
  32. GO
  33. ALTER TABLE [dbo].[Article] ADD DEFAULT ((0)) FOR [IsTop]
  34. GO
  35. ALTER TABLE [dbo].[Article] ADD DEFAULT ((0)) FOR [IsSlide]
  36. GO
  37. ALTER TABLE [dbo].[Article] ADD DEFAULT ((0)) FOR [IsRed]
  38. GO
  39. ALTER TABLE [dbo].[Article] ADD DEFAULT ((0)) FOR [IsPublish]
  40. GO
  41. ALTER TABLE [dbo].[Article] ADD DEFAULT ((0)) FOR [IsDeleted]
  42. GO
  43. ALTER TABLE [dbo].[Article] WITH CHECK ADD CONSTRAINT [FK_ARTICLE_RELATIONS_ARTICLEC] FOREIGN KEY([CategoryId])
  44. REFERENCES [dbo].[ArticleCategory] ([Id])
  45. GO
  46. ALTER TABLE [dbo].[Article] CHECK CONSTRAINT [FK_ARTICLE_RELATIONS_ARTICLEC]
  47. GO
复制代码
 
那么对应的Article Model代码如下:
  1. public class Article
  2. {
  3. /// <summary>
  4. /// 主键
  5. /// </summary>
  6. [Key]
  7. public Int32 Id { get; set; }
  8. /// <summary>
  9. /// 分类ID
  10. /// </summary>
  11. [Required]
  12. public Int32 CategoryId { get; set; }
  13. /// <summary>
  14. /// 文章标题
  15. /// </summary>
  16. [Required]
  17. public String Title { get; set; }
  18. /// <summary>
  19. /// 图片地址
  20. /// </summary>
  21. public String ImageUrl { get; set; }
  22. /// <summary>
  23. /// 文章内容
  24. /// </summary>
  25. public String Content { get; set; }
  26. /// <summary>
  27. /// 浏览次数
  28. /// </summary>
  29. [Required]
  30. public Int32 ViewCount { get; set; }
  31. /// <summary>
  32. /// 排序
  33. /// </summary>
  34. [Required]
  35. public Int32 Sort { get; set; }
  36. /// <summary>
  37. /// 作者
  38. /// </summary>
  39. public String Author { get; set; }
  40. /// <summary>
  41. /// 来源
  42. /// </summary>
  43. public String Source { get; set; }
  44. /// <summary>
  45. /// SEO标题
  46. /// </summary>
  47. public String SeoTitle { get; set; }
  48. /// <summary>
  49. /// SEO关键字
  50. /// </summary>
  51. public String SeoKeyword { get; set; }
  52. /// <summary>
  53. /// SEO描述
  54. /// </summary>
  55. public String SeoDescription { get; set; }
  56. /// <summary>
  57. /// 添加人ID
  58. /// </summary>
  59. [Required]
  60. public Int32 AddManagerId { get; set; }
  61. /// <summary>
  62. /// 添加时间
  63. /// </summary>
  64. [Required]
  65. public DateTime AddTime { get; set; }
  66. /// <summary>
  67. /// 修改人ID
  68. /// </summary>
  69. public Int32? ModifyManagerId { get; set; }
  70. /// <summary>
  71. /// 修改时间
  72. /// </summary>
  73. public DateTime? ModifyTime { get; set; }
  74. /// <summary>
  75. /// 是否置顶
  76. /// </summary>
  77. public Boolean IsTop { get; set; }
  78. /// <summary>
  79. /// 是否轮播显示
  80. /// </summary>
  81. public Boolean IsSlide { get; set; }
  82. /// <summary>
  83. /// 是否热门
  84. /// </summary>
  85. public Boolean IsRed { get; set; }
  86. /// <summary>
  87. /// 是否发布
  88. /// </summary>
  89. public Boolean IsPublish { get; set; }
  90. /// <summary>
  91. /// 是否删除
  92. /// </summary>
  93. [Required]
  94. public Boolean IsDeleted { get; set; }
  95. }
复制代码
 
(2).视图Create代码
(2.1)视图代码
考虑到要同时上传图片,注意form表单的额 enctype类型;
  1. @{ ViewData["Title"] = "新建文章"; }
  2. @model Article
  3. <form action="/Article/Create" method="post" enctype="multipart/form-data">
  4. @Html.AntiForgeryToken()
  5. <label asp-for="Title">标题</label>
  6. <input type="text" asp-for="Title" name="Title" placeholder="请输入标题">
  7. <label asp-for="CategoryId">文章类型</label>
  8. @Html.DropDownList("ddl_CategoryId", ViewBag.database as IEnumerable<SelectListItem>)
  9. <label>设置</label>
  10. @*@Html.CheckBox("IsTop") 置顶
  11. @Html.CheckBox("IsRed") 热点
  12. @Html.CheckBox("IsSlide") 幻灯*@
  13. <input type="checkbox" name="IsTop" asp-for="IsTop" />置顶
  14. <input type="checkbox" name="IsRed" asp-for="IsRed"/>热点
  15. <input type="checkbox" name="IsSlide" asp-for="IsSlide" />幻灯
  16. <label asp-for="ImageUrl">文章首页图</label>
  17. <input type="file" asp-for="ImageUrl" name="ImageUrl"/>
  18. <label asp-for="Content">内容</label>
  19. <textarea placeholder="内容" asp-for="Content" name="Content" cols="30" rows="10"></textarea>
  20. <label asp-for="Sort">排序</label>
  21. <input type="text" placeholder="排序" asp-for="Sort" name="Sort" />
  22. <label asp-for="ViewCount">点击量</label>
  23. <input type="text" placeholder="点击量" asp-for="ViewCount" name="ViewCount" />
  24. <label asp-for="IsPublish">是否发布</label>
  25. <select asp-for="IsPublish" name="IsPublish" class="IsPublish">
  26. <option value="False">否</option>
  27. <option value="True" selected>是</option>
  28. </select>
  29. <label asp-for="Author">作者</label>
  30. <input type="text" asp-for="Author" name="Author" placeholder="作者名">
  31. <label asp-for="Source">来源</label>
  32. <input type="text" asp-for="Source" name="Source" placeholder="文章来源">
  33. <label asp-for="SeoTitle">SEO标题</label>
  34. <input type="text" asp-for="SeoTitle" name="SeoTitle" placeholder="SEO标题">
  35. <label asp-for="SeoKeyword">SEO关键词</label>
  36. <input type="text" asp-for="SeoKeyword" name="SeoKeyword" placeholder="SEO关键词">
  37. <label asp-for="SeoDescription">SEO摘要描述</label>
  38. <input type="text" asp-for="SeoDescription" name="SeoDescription" placeholder="SEO摘要描述">
  39. <button type="submit">确定</button>
  40. <button type="reset">重置</button>
  41. </form>
复制代码
 
(2.2)视图中的下拉框的实现方式(递归和循环嵌套)

我想在添加文章时,实现一个具有二级层次结构的下拉框,如上图所示。所以,在对下拉框进行数据绑定时,就要费点功夫,上个章节讲文章类别管理时,的表结构就一个,分类都存在一张表中,所以要进行递归的获取子菜单或者通过循环嵌套来实现。
递归的主要核心函数为:
  1. /// <summary>
  2. /// 递归函数,实现获取子菜单
  3. /// </summary>
  4. /// <param name="lists">递归前的列表</param>
  5. /// <param name="newlists">递归后的新列表</param>
  6. /// <param name="parentId">父Id</param>
  7. /// <returns></returns>
  8. public static List<CategorySelectItemListView> GetChildCategory(List<CategorySelectItemListView> lists, List<CategorySelectItemListView> newlists, int parentId)
  9. {
  10. newlists = new List<CategorySelectItemListView>();
  11. List<CategorySelectItemListView> tempList = lists.Where(c => c.ParentId == parentId).ToList();
  12. for (int i = 0; i < tempList.Count; i++)
  13. {
  14. CategorySelectItemListView category = new CategorySelectItemListView();
  15. category.Id = tempList[i].Id;
  16. category.ParentId = tempList[i].ParentId;
  17. category.Title = tempList[i].Title;
  18. category.Children = GetChildCategory(lists, newlists, category.Id);
  19. newlists.Add(category);
  20. }
  21. return newlists;
  22. }
  23. /// <summary>
  24. /// 循环嵌套,实现获取子菜单
  25. /// </summary>
  26. /// <param name="lists">循环遍历前的列表</param>
  27. /// <returns></returns>
  28. public static List<CategorySelectItemListView> GetChildCategory(List<CategorySelectItemListView> lists)
  29. {
  30. List<CategorySelectItemListView> categorylist = new List<CategorySelectItemListView>();
  31. for (int i = 0; i < lists.Count; i++)
  32. {
  33. if (0 == lists[i].ParentId)
  34. categorylist.Add(lists[i]);
  35. for (int j = 0; j < lists.Count; j++)
  36. {
  37. if (lists[j].ParentId == lists[i].Id)
  38. lists[i].Children.Add(lists[j]);
  39. }
  40. }
  41. return categorylist;
  42. }
复制代码
 
然后在Create和Edit的Action中去绑定对应的下拉菜单即可。
注意:List 集合的CategorySelectItemListView,这个是新建的ViewModel对象,用来专门绑定下拉菜单使用,其代码如下:
  1. public class CategorySelectItemListView
  2. {
  3. public int Id { get; set; }
  4. public string Title { get; set; }
  5. public int ParentId { get; set; }
  6. public List<CategorySelectItemListView> Children { get; set; }
  7. public CategorySelectItemListView()
  8. {
  9. Children = new List<CategorySelectItemListView>();
  10. }
  11. public CategorySelectItemListView(int id,string title,int parentid)
  12. {
  13. this.Id = id;
  14. this.Title = title;
  15. this.ParentId = parentid;
  16. Children = new List<CategorySelectItemListView>();
  17. }
  18. public CategorySelectItemListView(int id, string title, CategorySelectItemListView parent)
  19. {
  20. this.Id = id;
  21. this.Title = title;
  22. this.ParentId = parent.Id;
  23. Children = new List<CategorySelectItemListView>();
  24. }
复制代码
 
(3).视图Edit代码,注解部分的代码可以参考,我尝试用过,也可以达到目的,演练代码最好是用多种方式实现,查看其区别,这样掌握的牢固一些
  1. @{ ViewData["Title"] = "编辑文章"; }
  2. @model Article
  3. @section Scripts{
  4. }
  5. <form action="/Article/Edit" method="post" enctype="multipart/form-data">
  6. @Html.AntiForgeryToken()
  7. <label asp-for="Title">标题</label>
  8. <input type="text" asp-for="Title" name="Title" placeholder="请输入标题">
  9. <input type="hidden" asp-for="Id" />
  10. <label asp-for="CategoryId">文章类型</label>
  11. @Html.DropDownList("ddl_CategoryId", ViewBag.database as IEnumerable<SelectListItem>)
  12. <label>设置</label>
  13. @*@Html.CheckBox("IsTop", Model.IsTop,new { value = Model.IsTop}) 置顶
  14. @Html.CheckBox("IsRed", Model.IsRed, new { value = Model.IsRed }) 热点
  15. @Html.CheckBox("IsSlide", Model.IsSlide, new { value = Model.IsSlide }) 幻灯*@
  16. <input asp-for="IsTop" />置顶
  17. <input asp-for="IsRed" />热点
  18. <input asp-for="IsSlide" />幻灯
  19. @*<input type="checkbox" name="IsTop" @(Html.Raw(@Model.IsTop ? "checked="checked"" : "")) asp-for="IsTop" />置顶
  20. <input type="checkbox" name="IsRed" @(Html.Raw(@Model.IsRed ? "checked="checked"" : "")) asp-for="IsRed" />热点
  21. <input type="checkbox" name="IsSlide" @(Html.Raw(@Model.IsSlide ? "checked="checked"" : "")) asp-for="IsSlide" />幻灯*@
  22. @*<input type="checkbox" name="IsTop" asp-for="IsTop" />置顶
  23. <input type="checkbox" name="IsRed" asp-for="IsRed"/>热点
  24. <input type="checkbox" name="IsSlide" asp-for="IsSlide"/>幻灯*@
  25. <label asp-for="ImageUrl">文章首页图</label>
  26. <input type="file" asp-for="ImageUrl" name="ImageUrl" />
  27. <label asp-for="ImageUrl">@Model.ImageUrl</label>
  28. <label asp-for="Content">内容</label>
  29. <textarea placeholder="内容" asp-for="Content" name="Content" cols="30" rows="10"></textarea>
  30. <label asp-for="Sort">排序</label>
  31. <input type="text" placeholder="排序" asp-for="Sort" name="Sort" />
  32. <label asp-for="ViewCount">点击量</label>
  33. <input type="text" placeholder="点击量" asp-for="ViewCount" name="ViewCount" />
  34. <label asp-for="IsPublish">是否发布</label>
  35. <select asp-for="IsPublish" name="IsPublish" class="IsPublish">
  36. <option value="False">否</option>
  37. <option value="True" selected>是</option>
  38. </select>
  39. <label asp-for="Author">作者</label>
  40. <input type="text" asp-for="Author" name="Author" placeholder="作者名">
  41. <label asp-for="Source">来源</label>
  42. <input type="text" asp-for="Source" name="Source" placeholder="文章来源">
  43. <label asp-for="SeoTitle">SEO标题</label>
  44. <input type="text" asp-for="SeoTitle" name="SeoTitle" placeholder="SEO标题">
  45. <label asp-for="SeoKeyword">SEO关键词</label>
  46. <input type="text" asp-for="SeoKeyword" name="SeoKeyword" placeholder="SEO关键词">
  47. <label asp-for="SeoDescription">SEO摘要描述</label>
  48. <input type="text" asp-for="SeoDescription" name="SeoDescription" placeholder="SEO摘要描述">
  49. <button type="submit">确定</button>
  50. <button type="reset">重置</button>
  51. </form>
复制代码
 
(4).视图Index列表的代码
针对列表的显示,又专门编写了ArticeView的这个ViewModel。
  1. public class ArticleView
  2. {
  3. public int Id { get; set; }
  4. public int CategoryId { get; set; }
  5. public string CategoryName { get; set; }
  6. public string Title { get; set; }
  7. public int ViewCount { get; set; }
  8. public int Sort { get; set; }
  9. public string Author { get; set; }
  10. public string Source { get; set; }
  11. public int AddManagerId { get; set; }
  12. public DateTime AddTime { get; set; }
  13. }
复制代码
 
  1. @using Humanizer;
  2. @using RjWebCms.Db;
  3. @using RjWebCms.Models.Articles;
  4. @model PaginatedList<ArticleView>
  5. @{
  6. ViewData["Title"] = "文章列表";
  7. }
  8. @section Scripts{
  9. }
  10. @ViewData["Title"]
  11. @Html.AntiForgeryToken()
  12. <form asp-action="Index" method="get">
  13. <table>
  14. <tr><td><a asp-controller="Article" asp-action="Create">添加</a></td></tr>
  15. <tr>
  16. <td>查询关键词:<input type="text" name="SearchString" value="@ViewData["CurrentFilter"]" /></td>
  17. <td><input type="submit" value="查询" /></td>
  18. <td><a asp-action="Index">Back</a></td>
  19. <td><a asp-action="DeleteAll">批量删除</a></td>
  20. </tr>
  21. </table>
  22. </form>
  23. <table class="table table-hover">
  24. <thead>
  25. <tr>
  26. <td>✔</td>
  27. <td><a asp-action="Index" asp-route-sortOrder="@ViewData["NameSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">标题</a></td>
  28. <td>类别</td>
  29. <td><a asp-action="Index" asp-route-sortOrder="@ViewData["DateSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">添加时间</a></td>
  30. <td>作者</td>
  31. <td>操作</td>
  32. </tr>
  33. @foreach (var item in Model)
  34. {
  35. <tr>
  36. <td><input type="checkbox" class="done-checkbox" name="chk_ids" value="@item.Id"></td>
  37. <td>@item.Title</td>
  38. <td>@item.CategoryName</td>
  39. <td>@item.AddTime</td>
  40. <td>@item.Author</td>
  41. <td>
  42. <a asp-action="Details" asp-route-id="@item.Id">Details</a>
  43. <a asp-action="Edit" asp-route-id="@item.Id">Edit</a>
  44. <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
  45. </td>
  46. </tr>
  47. }
  48. </thead>
  49. </table>
  50. @{
  51. var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
  52. var nextDisabled = !Model.HasNextPage ? "disabled" : ""; ;
  53. }
  54. <a asp-action="Index"
  55. asp-route-sortOrder="@ViewData["CurrentSort"]"
  56. asp-route-pageNumber="@(Model.PageIndex - 1)"
  57. asp-route-currentFilter="@ViewData["CurrentFilter"]"
  58. class="btn btn-default @prevDisabled">
  59. 上一页
  60. </a>
  61. <a asp-action="Index"
  62. asp-route-sortOrder="@ViewData["CurrentSort"]"
  63. asp-route-pageNumber="@(Model.PageIndex + 1)"
  64. asp-route-currentFilter="@ViewData["CurrentFilter"]"
  65. class="btn btn-default @nextDisabled">
  66. 下一页
  67. </a>
复制代码
 
(5).Controller部分的全部代码,注意看代码注释
  1. public class ArticleController : Controller
  2.     {
  3.         private readonly IHostEnvironment _hostEnvironment;
  4.         private readonly IArticleService _articleService;
  5.         private readonly IArticleCategoryService _articleCategoryService;
  6.         private readonly AppDbContext _appDbContext;
  7.         public ArticleController(IArticleService articleService, IArticleCategoryService articleCategoryService,AppDbContext appDbContext,IHostEnvironment hostEnvironment)
  8.         {
  9.             _hostEnvironment = hostEnvironment;
  10.             _appDbContext = appDbContext;
  11.             _articleService = articleService;
  12.             _articleCategoryService = articleCategoryService;
  13.         }
  14.         public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? pageNumber)
  15.         {
  16.             ViewData["CurrentSort"] = sortOrder;
  17.             ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
  18.             ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
  19.             if (searchString != null)
  20.             {
  21.                 pageNumber = 1;
  22.             }
  23.             else
  24.             {
  25.                 searchString = currentFilter;
  26.             }
  27.             ViewData["CurrentFilter"] = searchString;
  28.             var article = from s in _appDbContext.Article
  29.                           join p in _appDbContext.ArticleCategory on s.CategoryId equals p.Id
  30.                           select new ArticleView {
  31.                             Id = s.Id,
  32.                             CategoryId = s.CategoryId,
  33.                             CategoryName = p.Title,
  34.                             Title = s.Title,
  35.                             Sort = s.Sort,
  36.                             AddManagerId = s.AddManagerId,
  37.                             AddTime = s.AddTime,
  38.                             Author = s.Author,
  39.                             Source = s.Source,
  40.                             ViewCount = s.ViewCount,
  41.                           };
  42.             if (!string.IsNullOrEmpty(searchString))
  43.             {
  44.                 article = article.Where(s => s.Title.Contains(searchString));
  45.             }
  46.             switch (sortOrder)
  47.             {
  48.                 case "name_desc":
  49.                     article = article.OrderByDescending(s => s.Title) ;
  50.                     break;
  51.                 case "Date":
  52.                     article = article.OrderBy(s => s.AddTime);
  53.                     break;
  54.                 case "date_desc":
  55.                     article = article.OrderByDescending(s => s.AddTime);
  56.                     break;
  57.                 default:
  58.                     article = article.OrderBy(s => s.Title);
  59.                     break;
  60.             }
  61.             int pageSize = 4;
  62.             return View(await PaginatedList<ArticleView>.CreateAsync(article.AsNoTracking(), pageNumber ?? 1, pageSize));
  63.         }
  64.         [HttpGet]
  65.         public async Task<IActionResult> CreateAsync()
  66.         {
  67.             #region 绑定类别下拉框
  68.             var categories = await _articleCategoryService.GetArticleCategory();//列出文章类别字典
  69.             var categoryItems = new List<SelectListItem>()
  70.             {
  71.                 new SelectListItem(){ Value="0",Text="全部",Selected=true}
  72.             };
  73.             //全部列出并转成DropDownList对象
  74.             List<CategorySelectItemListView> list = new List<CategorySelectItemListView>();
  75.             foreach (var category in categories)
  76.             {
  77.                 list.Add(new CategorySelectItemListView {
  78.                     Id=category.Id,
  79.                     Title = category.Title,
  80.                     ParentId = category.ParentId
  81.                 });
  82.             }
  83.             #region 循环嵌套调用
  84.             //List<CategorySelectItemListView> list1 = GetChildCategory(list);
  85.             //foreach (var li in list1)
  86.             //{
  87.             //    categoryItems.Add(new SelectListItem { Value = li.Id.ToString(), Text = li.Title });
  88.             //    if (li.Children.Count > 0)
  89.             //    {
  90.             //        foreach(var t in li.Children)
  91.             //            categoryItems.Add(new SelectListItem { Value = t.Id.ToString(),Text= "|-" + t.Title });
  92.             //    }
  93.             //}
  94.             #endregion
  95.             #region  递归调用
  96.             List<CategorySelectItemListView> list1 = GetChildCategory(list, new List<CategorySelectItemListView>(), 0);
  97.             foreach (var li in list1)
  98.             {
  99.                 categoryItems.Add(new SelectListItem { Value = li.Id.ToString(), Text = li.Title });
  100.                 if (li.Children.Count > 0)
  101.                 {
  102.                     foreach (var t in li.Children)
  103.                         categoryItems.Add(new SelectListItem { Value = t.Id.ToString(), Text = "  |-" + t.Title });
  104.                 }
  105.             }
  106.             #endregion
  107.             ViewBag.database = categoryItems;
  108.             #endregion
  109.             return View();
  110.         }
  111.         [HttpPost]
  112.         [ValidateAntiForgeryToken]
  113.         public async Task<IActionResult> CreateAsync(Article article,[FromForm]IFormCollection fromData)
  114.         {
  115.             //去掉对字段IsSystem的验证,IsSystem在数据库是bool类型,而前端是0和1,ModelState的验证总是报false,所以去掉对其验证
  116.             //ModelState.Remove("IsSystem");//在View端已经解决了了bool类型,那么此行代码可以不用
  117.             #region 下拉菜单
  118.             string strCategoryId = Request.Form["ddl_CategoryId"];
  119.             if (!string.IsNullOrEmpty(strCategoryId))
  120.                 article.CategoryId = int.Parse(strCategoryId);
  121.             else
  122.                 article.CategoryId = 0;
  123.             #endregion
  124.             #region 复选框
  125.             article.IsTop = fromData["IsTop"] != "false";//使用FormCollection时,可以这样
  126.             article.IsRed = fromData["IsRed"] != "false";
  127.             article.IsSlide = fromData["IsSlide"] != "false";
  128.             //也可以这样取值,但要注意View内的写法
  129.             //if (!string.IsNullOrEmpty(fromData["IsTop"]))
  130.             //    article.IsTop = true;
  131.             //else
  132.             //    article.IsTop = false;
  133.             #endregion
  134.             #region 上传文件
  135.             IFormFileCollection files = fromData.Files;
  136.            foreach(var formFile in files)
  137.             {
  138.                 //var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
  139.                 string webContentPath = _hostEnvironment.ContentRootPath;
  140.                 var fileExt = formFile.FileName.Substring(formFile.FileName.LastIndexOf('.'));//文件扩展名
  141.                 var fileNew = DateTime.Now.ToString("yyyyMMddHHmmss") + fileExt; //给文件重新命名
  142.                
  143.                 //string upLoadPath = webContentPath + $@"\{fileName}";
  144.                 string upLoadPath = webContentPath + $@"\UpFiles";
  145.                 var fileUrl = upLoadPath + $@"\{fileNew}";
  146.                 if (formFile.Length > 0)
  147.                 {
  148.                     using (var stream = new FileStream(fileUrl,FileMode.Create))
  149.                     {
  150.                         await formFile.CopyToAsync(stream);
  151.                     }
  152.                 }
  153.                 article.ImageUrl = "../UpFiles/" + fileNew;
  154.             }      
  155.             #endregion
  156.             if (ModelState.IsValid)
  157.             {
  158.                 var successful = await _articleService.AddArticleAysnc(article);
  159.                 if (successful)
  160.                     return RedirectToAction("Index");
  161.                 else
  162.                     return BadRequest("失败");
  163.             }
  164.             return View(article);
  165.         }
  166.         [HttpGet]
  167.         public async Task<IActionResult> Edit(int id)
  168.         {
  169.             if (string.IsNullOrEmpty(id.ToString()))
  170.                 return NotFound();
  171.             var article = await _articleService.FindArticleAsync(id);
  172.             if (article == null)
  173.                 return NotFound();
  174.             #region 绑定角色下拉框
  175.             var categories = await _articleCategoryService.GetArticleCategory();//列出文章类别字典
  176.             var categoryItems = new List<SelectListItem>()
  177.             {
  178.                 new SelectListItem(){ Value="0",Text="全部",Selected=true}
  179.             };
  180.             //全部列出并转成DropDownList对象
  181.             List<CategorySelectItemListView> list = new List<CategorySelectItemListView>();
  182.             foreach (var category in categories)
  183.             {
  184.                 list.Add(new CategorySelectItemListView
  185.                 {
  186.                     Id = category.Id,
  187.                     Title = category.Title,
  188.                     ParentId = category.ParentId
  189.                 });
  190.             }
  191.             #region  递归调用
  192.             List<CategorySelectItemListView> list1 = GetChildCategory(list, new List<CategorySelectItemListView>(), 0);
  193.             foreach (var li in list1)
  194.             {
  195.                 categoryItems.Add(new SelectListItem { Value = li.Id.ToString(), Text = li.Title });
  196.                 if (li.Children.Count > 0)
  197.                 {
  198.                     foreach (var t in li.Children)
  199.                         categoryItems.Add(new SelectListItem { Value = t.Id.ToString(), Text = "  |-" + t.Title });
  200.                 }
  201.             }
  202.             #endregion
  203.             #region 遍历并选中
  204.             foreach (SelectListItem item in categoryItems)
  205.             {
  206.                 if (item.Value == article.CategoryId.ToString())
  207.                     item.Selected = true;
  208.             }
  209.             #endregion
  210.             ViewBag.database = categoryItems;
  211.             #endregion
  212.             return View(article);
  213.         }
  214.         [HttpPost]
  215.         [ValidateAntiForgeryToken]
  216.         public async Task<IActionResult> Edit(int id, [FromForm]Article article)
  217.         {
  218.             if (id != article.Id)
  219.             {
  220.                 return NotFound();
  221.             }
  222.             #region 下拉菜单
  223.             string strCategoryId = Request.Form["ddl_CategoryId"];
  224.             if (!string.IsNullOrEmpty(strCategoryId))
  225.                 article.CategoryId = int.Parse(strCategoryId);
  226.             else
  227.                 article.CategoryId = 0;
  228.             #endregion
  229.             #region 复选框
  230.             if (Request.Form["IsTop"].Contains("true"))
  231.                 article.IsTop = true;
  232.             else
  233.                 article.IsTop = false;
  234.             if (Request.Form["IsRed"].Contains("true"))
  235.                 article.IsRed = true;
  236.             else
  237.                 article.IsRed = false;
  238.             if (Request.Form["IsSlide"].Contains("true"))
  239.                 article.IsSlide = true;
  240.             else
  241.                 article.IsSlide = false;
  242.             #endregion
  243.             //ModelState.Remove("IsTop");
  244.             //ModelState.Remove("IsRed");
  245.             //ModelState.Remove("IsSlide");
  246.             if (ModelState.IsValid)
  247.             {
  248.                 try
  249.                 {
  250.                     var result = await _articleService.UpdateArticleAsync(id, article);
  251.                     //跳转
  252.                     if (result)
  253.                         return RedirectToAction("Index");
  254.                     else
  255.                         return BadRequest("编辑失败");
  256.                 }
  257.                 catch (Exception ex)
  258.                 {
  259.                     return BadRequest("编辑失败");
  260.                 }
  261.             }
  262.             else
  263.             {
  264.                 return BadRequest("数据输入有误!");
  265.             }
  266.         }
  267.         /// <summary>
  268.         /// 递归函数,实现获取子菜单
  269.         /// </summary>
  270.         /// <param name="lists">递归前的列表</param>
  271.         /// <param name="newlists">递归后的新列表</param>
  272.         /// <param name="parentId">父Id</param>
  273.         /// <returns></returns>
  274.         public static List<CategorySelectItemListView> GetChildCategory(List<CategorySelectItemListView> lists, List<CategorySelectItemListView> newlists, int parentId)
  275.         {
  276.             newlists = new List<CategorySelectItemListView>();
  277.             List<CategorySelectItemListView> tempList = lists.Where(c => c.ParentId == parentId).ToList();
  278.             for (int i = 0; i < tempList.Count; i++)
  279.             {
  280.                 CategorySelectItemListView category = new CategorySelectItemListView();
  281.                 category.Id = tempList[i].Id;
  282.                 category.ParentId = tempList[i].ParentId;
  283.                 category.Title = tempList[i].Title;
  284.                 category.Children = GetChildCategory(lists, newlists, category.Id);
  285.                 newlists.Add(category);
  286.             }
  287.             return newlists;
  288.         }
  289.         /// <summary>
  290.         /// 循环嵌套,实现获取子菜单
  291.         /// </summary>
  292.         /// <param name="lists">循环遍历前的列表</param>
  293.         /// <returns></returns>
  294.         public static List<CategorySelectItemListView> GetChildCategory(List<CategorySelectItemListView> lists)
  295.         {
  296.             List<CategorySelectItemListView> categorylist = new List<CategorySelectItemListView>();
  297.             for (int i = 0; i < lists.Count; i++)
  298.             {
  299.                 if (0 == lists[i].ParentId)
  300.                     categorylist.Add(lists[i]);
  301.                 for (int j = 0; j < lists.Count; j++)
  302.                 {
  303.                     if (lists[j].ParentId == lists[i].Id)
  304.                         lists[i].Children.Add(lists[j]);
  305.                 }
  306.             }
  307.             return categorylist;
  308.         }
  309.     }
复制代码
 
(6).Service应用层代码

 
  1.     public class ArticleService : IArticleService
  2.     {
  3.         private readonly AppDbContext _appDbContext;
  4.         public ArticleService(AppDbContext appDbContext)
  5.         {
  6.             _appDbContext = appDbContext;
  7.         }
  8.         /// <summary>
  9.         /// 添加文章
  10.         /// </summary>
  11.         /// <param name="article"></param>
  12.         /// <returns></returns>
  13.         public async Task<bool> AddArticleAysnc(Article article)
  14.         {
  15.             article.IsDeleted = false;
  16.             article.AddManagerId = 1;//用户id
  17.             article.AddTime = DateTime.Now;
  18.             article.IsPublish = true;
  19.             await _appDbContext.Article.AddAsync(article);
  20.             var result = await _appDbContext.SaveChangesAsync();
  21.             return result == 1;
  22.         }
  23.         /// <summary>
  24.         /// 删除文章
  25.         /// </summary>
  26.         /// <param name="Id"></param>
  27.         /// <returns></returns>
  28.         public async Task<bool> DeleteArticleAsync(int Id)
  29.         {
  30.             var article = await _appDbContext.Article.FirstOrDefaultAsync(x => x.Id == Id);
  31.             if (article != null)
  32.             {
  33.                 _appDbContext.Article.Remove(article);
  34.             }
  35.             var result = await _appDbContext.SaveChangesAsync();
  36.             return result == 1; //注意(result==1 如果等式成立,则返回true,说明删除成功)
  37.         }
  38.         /// <summary>
  39.         /// 按Id查询文章
  40.         /// </summary>
  41.         /// <param name="Id"></param>
  42.         /// <returns></returns>
  43.         public async Task<Article> FindArticleAsync(int Id)
  44.         {
  45.             var item = await _appDbContext.Article.Where(x => x.Id == Id).FirstOrDefaultAsync();
  46.             return item;
  47.         }
  48.         /// <summary>
  49.         /// 按标题查询文章
  50.         /// </summary>
  51.         /// <param name="title"></param>
  52.         /// <returns></returns>
  53.         public async Task<Article[]> GetArtcleByTitle(string title)
  54.         {
  55.             var items = await _appDbContext.Article.Where(x => x.Title.Contains(title)).ToArrayAsync();
  56.             return items;
  57.         }
  58.         /// <summary>
  59.         /// 查询文章
  60.         /// </summary>
  61.         /// <returns></returns>
  62.         public async Task<Article[]> GetArticles()
  63.         {
  64.             var items = await _appDbContext.Article.Where(x => x.IsDeleted==false).ToArrayAsync();
  65.             return items;
  66.         }
  67.         /// <summary>
  68.         /// 更新文章
  69.         /// </summary>
  70.         /// <param name="id"></param>
  71.         /// <param name="article"></param>
  72.         /// <returns></returns>
  73.         public async Task<bool> UpdateArticleAsync(int id, Article article)
  74.         {
  75.             var oldArticle = await  FindArticleAsync(id); //找出旧对象
  76.             //将新值赋到旧对象上
  77.             oldArticle.Title = article.Title;
  78.             oldArticle.CategoryId = article.CategoryId;
  79.             oldArticle.SeoDescription = article.SeoDescription;
  80.             oldArticle.SeoTitle = article.SeoTitle;
  81.             oldArticle.SeoKeyword = article.SeoKeyword;
  82.             oldArticle.Content = article.Content;
  83.             oldArticle.Sort = article.Sort;
  84.             oldArticle.Source = article.Source;
  85.             oldArticle.IsSlide = article.IsSlide;
  86.             oldArticle.IsPublish = article.IsPublish;
  87.             oldArticle.IsRed = article.IsRed;
  88.             oldArticle.IsTop = article.IsTop;
  89.             oldArticle.ViewCount = article.ViewCount;
  90.             oldArticle.Author = article.Author;
  91.             oldArticle.ImageUrl = article.ImageUrl;
  92.             oldArticle.ModifyManagerId = 11;//
  93.             oldArticle.ModifyTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
  94.             //对旧对象执行更新
  95.             _appDbContext.Entry(oldArticle).State = EntityState.Modified;
  96.             var result = await _appDbContext.SaveChangesAsync();
  97.             return result == 1;
  98.         }
  99.     }
复制代码
 
 
再谈CheckBox的使用
1.在View视图页增加的代码格式如果为:
置顶
或者是这样:
置顶
那么在生成的html代码中,都会自动成id,name,type=“checkbox” value的属性。
2.在Controller中进行取值时的代码为:
if (Request.Form["IsTop"].Contains("true"))
article.IsTop = true;
else
article.IsTop = false;
跟踪时发现,View中Checkbox选中是,会产生true和false两个值,如图跟踪变量发现:

如此,取值时,就用了Contains功能,因为View中CheckBox没选中,这只有一个false值;
3.在View视图页增加代码的格式如果为:
置顶
4.在Controller中进行取值时的代码为:
if (!string.IsNullOrEmpty(Request.Form["IsTop"]))
article.IsTop = true;
else
article.IsTop = false;
跟踪时发现,View中的CheckBox选中是,取到的值为“on”,如图跟踪发现:

所以,才用了IsNullOrEmpty这个函数,依据判空来确定是否选中。
但是这样写有个问题,在ModelState.IsValid()的模型验证中,一直无法通过,IsTop一直为false,为此,我干脆就把其去除掉验证:
ModelState.Remove("IsTop");//去除name=IsTop的checkbox的模型验证
5.使用Checkbox,还是要看给在数据表中为其定义的字段类型,Model中的指定类型和验证属性,如果你赋予了Value值,那么就在Controller中取值,Asp.Net Core中Checkbox默认是True和False的值,网上关于@Html.CheckBox()形式也行,你可以尝试跟踪变量值来判断如何处理,其宗旨就是根据具体条件来处理。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美食家大橙子

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表