随着技术的进步,跨平台开发已经成为了标配,在此大背景下,ASP.NET Core也应运而生。本文主要利用ASP.NET Core开发一个学生管理系统为例,简述ASP.NET Core开发的常见知识点,前一篇文章做了登录功能,本文继续分享开发主页面功能。仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
开发学生管理系统,涉及知识点,如下所示:
- 开发工具:Visual Studio 2019
- 目标框架:.Net 5.0
- 架构:MVC三层架构【Model-View-Controller】
页面布局
主页面中主要分为三部分上【header】,中【左侧菜单栏,右侧内容区域】,下【footer】,示意图如下所示:
创建模型
在主页面,左侧的菜单需要根据不同的用户进行不同的显示,所以需要创建菜单-用户-角色对应的模型,如下所示:
1. 菜单【Menu】模型
Menu模型,如下所示:
1 namespace SMS.Models 2 { 3 /// <summary> 4 /// 菜单管理 5 /// </summary> 6 public class Menu 7 { 8 /// <summary> 9 /// 唯一标识 10 /// </summary> 11 public int Id { get; set; } 12 13 /// <summary> 14 /// 菜单名称 15 /// </summary> 16 public string Name { get; set; } 17 18 /// <summary> 19 /// 菜单描述 20 /// </summary> 21 public string Description { get; set; } 22 23 /// <summary> 24 /// 菜单路径 25 /// </summary> 26 public string Url { get; set; } 27 28 /// <summary> 29 /// 父ID 30 /// </summary> 31 public int? ParentId { get; set; } 32 33 /// <summary> 34 /// 排序 35 /// </summary> 36 public int? SortId { get; set; } 37 } 38 }
2. 角色【Role】模型
角色模型,如下所示:
1 namespace SMS.Models 2 { 3 /// <summary> 4 /// 角色 5 /// </summary> 6 public class Role 7 { 8 /// <summary> 9 /// 唯一标识 10 /// </summary> 11 public int Id { get; set; } 12 13 /// <summary> 14 /// 角色名称 15 /// </summary> 16 public string Name { get; set; } 17 18 /// <summary> 19 /// 角色描述 20 /// </summary> 21 public string Description { get; set; } 22 } 23 }
3. 角色-菜单关联模型
角色-菜单关联模型【RoleMenu】,主要是将角色和菜单关联起来,如下所示:
1 namespace SMS.Models 2 { 3 /// <summary> 4 /// 角色-菜单关联 5 /// </summary> 6 public class RoleMenu 7 { 8 /// <summary> 9 /// 唯一标识 10 /// </summary> 11 public int Id { get; set; } 12 13 /// <summary> 14 /// 菜单IP 15 /// </summary> 16 public int MenuId { get; set; } 17 18 /// <summary> 19 /// 角色ID 20 /// </summary> 21 public int RoleId { get; set; } 22 } 23 }
4. 用户-角色模型
用户-角色模型,主要是将用户和角色关联起来,如下所示:
1 namespace SMS.Models 2 { 3 /// <summary> 4 /// 用户-角色模型 5 /// </summary> 6 public class UserRole 7 { 8 /// <summary> 9 /// 唯一标识 10 /// </summary> 11 public int Id { get; set; } 12 13 /// <summary> 14 /// 用户ID 15 /// </summary> 16 public int UserId { get; set; } 17 18 /// <summary> 19 /// 角色ID 20 /// </summary> 21 public int RoleId { get; set; } 22 } 23 }
5. 用户权限模型
将以上几种模型,查询出来就是用户所具备的权限,所以需要创建用户权限模型,如下所示:
1 namespace SMS.Models 2 { 3 /// <summary> 4 /// 用户-权限模型 5 /// </summary> 6 public class UserRight 7 { 8 /// <summary> 9 /// 唯一标识 10 /// </summary> 11 public int Id { get; set; } 12 13 /// <summary> 14 /// 角色名称 15 /// </summary> 16 public string RoleName { get; set; } 17 18 /// <summary> 19 /// 菜单名称 20 /// </summary> 21 public string MenuName { get; set; } 22 23 /// <summary> 24 /// 路径 25 /// </summary> 26 public string Url { get; set; } 27 28 /// <summary> 29 /// 父ID 30 /// </summary> 31 public int? ParentId { get; set; } 32 33 /// <summary> 34 /// 排序 35 /// </summary> 36 public int? SortId { get; set; } 37 } 38 }
创建控制器
主页面默认采用HomeController,如下所示:
1 namespace SMS.Controllers 2 { 3 public class HomeController : Controller 4 { 5 private readonly ILogger<HomeController> _logger; 6 7 private DataContext dataContext; 8 9 public HomeController(ILogger<HomeController> logger, DataContext context) 10 { 11 _logger = logger; 12 dataContext = context; 13 } 14 15 public IActionResult Index() 16 { 17 int? userId = HttpContext.Session.GetInt32("UserId"); 18 //判断是否登录 19 if (userId != null) 20 { 21 22 var user = dataContext.Users.FirstOrDefault(u=>u.Id== userId); 23 if (user != null) { 24 ViewBag.NickName = user.NickName; 25 ViewBag.UserRights = GetUserRights(); 26 } 27 return View(); 28 } 29 else 30 { 31 return Redirect("/Login"); 32 } 33 34 } 35 36 public IActionResult Privacy() 37 { 38 return View(); 39 } 40 41 [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 42 public IActionResult Error() 43 { 44 return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 45 } 46 47 public List<UserRight> GetUserRights() 48 { 49 int? userId = HttpContext.Session.GetInt32("UserId"); 50 if (userId != null) 51 { 52 var query = from u in dataContext.UserRoles 53 join r in dataContext.Roles on u.RoleId equals r.Id 54 join x in dataContext.RoleMenus on r.Id equals x.RoleId 55 join m in dataContext.Menus on x.MenuId equals m.Id 56 where u.UserId == userId 57 select new UserRight { Id=m.Id, RoleName = r.Name, MenuName = m.Name, Url = m.Url, ParentId = m.ParentId, SortId=m.SortId }; 58 59 return query.ToList(); 60 } 61 return null; 62 } 63 } 64 }
创建视图
主页面视图,位于Views/Home/Index.cshtml,如下所示:
1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 5 <html xmlns="http://www.w3.org/1999/xhtml"> 6 <head> 7 <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 8 <title>学生信息管理系统</title> 9 <link rel="stylesheet" type="text/css" href="/css/reset.css" media="screen" /> 10 <link rel="stylesheet" type="text/css" href="/css/text.css" media="screen" /> 11 <link rel="stylesheet" type="text/css" href="/css/grid.css" media="screen" /> 12 <link rel="stylesheet" type="text/css" href="/css/layout.css" media="screen" /> 13 <link rel="stylesheet" type="text/css" href="/css/nav.css" media="screen" /> 14 <!--[if IE 6]><link rel="stylesheet" type="text/css" href="css/ie6.css" media="screen" /><![endif]--> 15 <!--[if IE 7]><link rel="stylesheet" type="text/css" href="css/ie.css" media="screen" /><![endif]--> 16 <!-- BEGIN: load jquery --> 17 18 <script src="js/jquery-1.6.4.min.js" type="text/javascript"></script> 19 <script type="text/javascript" src="/js/jquery-ui/jquery.ui.core.min.js"></script> 20 <script src="/js/jquery-ui/jquery.ui.widget.min.js" type="text/javascript"></script> 21 <script src="/js/jquery-ui/jquery.ui.accordion.min.js" type="text/javascript"></script> 22 <script src="/js/jquery-ui/jquery.effects.core.min.js" type="text/javascript"></script> 23 <script src="/js/jquery-ui/jquery.effects.slide.min.js" type="text/javascript"></script> 24 <!-- END: load jquery --> 25 <script src="/js/setup.js" type="text/javascript"></script> 26 27 <script type="text/javascript"> 28 $(document).ready(function () { 29 30 //setupDashboardChart('chart1'); 31 32 setupLeftMenu(); 33 34 setSidebarHeight(); 35 }); 36 37 </script> 38 39 <style type="text/css"> 40 41 #demo-side-bar { 42 left: 90% !important; 43 display: block !important; 44 } 45 46 #branding .floatright { 47 margin-right: 130px !important; 48 } 49 </style> 50 51 </head> 52 <body> 53 <div class="container_12"> 54 55 <div class="grid_12 header-repeat"> 56 57 <div id="branding"> 58 59 <div class="floatleft"> 60 61 <h2 style="color:white;margin-top:unset;">学生信息管理系统</h2> 62 <br /> 63 </div> 64 65 <div class="floatright"> 66 67 <div class="floatleft"> 68 69 <img src="img/img-profile.jpg" alt="Profile Pic" /> 70 </div> 71 72 <div class="floatleft marginleft10"> 73 74 <ul class="inline-ul floatleft"> 75 76 <li>Hello <a href="#">@ViewBag.NickName</a></li> 77 78 <li><a href="#">Logout</a></li> 79 80 </ul> 81 82 <br /> 83 84 <span class="small grey">上次登录: 3 小时前</span> 85 86 </div> 87 88 </div> 89 90 <div class="clear"> 91 92 </div> 93 94 </div> 95 96 </div> 97 98 <div class="clear"> 99 100 </div> 101 102 <div class="grid_12"> 103 104 <ul class="nav main"> 105 106 <li class="ic-dashboard"><a href="#"><span>首页</span></a> </li> 107 108 <li class="ic-form-style"> 109 <a href="javascript:"><span>学生管理</span></a> 110 <ul> 111 112 <li><a href="form-controls.html">学生信息</a> </li> 113 </ul> 114 </li> 115 <li class="ic-form-style"> 116 <a href="javascript:"><span>成绩管理</span></a> 117 <ul> 118 119 <li><a href="form-controls.html">成绩信息</a> </li> 120 </ul> 121 </li> 122 <li class="ic-notifications"><a href="notifications.html"><span>Notifications</span></a></li> 123 124 </ul> 125 126 </div> 127 128 <div class="clear"> 129 130 </div> 131 132 <div class="grid_2"> 133 134 <div class="box sidemenu"> 135 136 <div class="block" id="section-menu"> 137 138 <ul class="section menu"> 139 @{ 140 var UserRights = ViewBag.UserRights as List<UserRight>; 141 //先取出一级菜单 142 var menuItems = UserRights.Where((u) => u.ParentId == null).OrderBy(u => u.SortId); 143 144 foreach (var menuItem in menuItems) 145 { 146 <li> 147 <a class="menuitem">@menuItem.MenuName</a> 148 <ul class="submenu"> 149 @{ var sumMenuItems = UserRights.Where(s => s.ParentId == menuItem.Id).OrderBy(s => s.SortId); 150 foreach (var subMenuItem in sumMenuItems) 151 { 152 <li><a href="@subMenuItem.Url">@subMenuItem.MenuName</a> </li> 153 } 154 } 155 156 </ul> 157 </li> 158 } 159 } 160 </ul> 161 162 </div> 163 164 </div> 165 </div> 166 167 <div class="grid_10" style="height:600px;"> 168 <iframe width="100%" height="100%"> 169 170 </iframe> 171 </div> 172 173 <div class="clear"> 174 175 </div> 176 </div> 177 <div class="clear"> 178 179 </div> 180 <div id="site_info"> 181 182 <p style="text-align:center"> 183 184 Copyright <a href="#">学生信息管理系统</a>. All Rights Reserved By 小六公子. 2021-2022 185 186 </p> 187 </div> 188 </body> 189 190 </html>
构建数据
在示例中,需要构建数据,用于显示菜单信息,数据表结构和模型保持一致。
1. 菜单表
菜单表,表结构及初始化数据,如下所示:
2. 角色表
角色表,表结构和初始化数据,如下所示:
3. 角色-菜单表
角色-菜单表,表示角色和菜单之间的对应关系。数据表结构和初始化数据,如下所示:
4. 用户-角色表
用户-角色表,主要用于配置用户ID和角色ID之间的对应关系,表结构和初始化数据,如下所示:
数据库集成DbContext
在示例中,通过Entity Framework Core来操作数据库,如下所示:
1 namespace SMS.Models 2 { 3 public class DataContext:DbContext 4 { 5 public DbSet<User> Users { get; set; } 6 7 public DbSet<Menu> Menus { get; set; } 8 9 public DbSet<Role> Roles { get; set; } 10 11 public DbSet<UserRole> UserRoles { get; set; } 12 13 public DbSet<RoleMenu> RoleMenus { get; set; } 14 15 public DataContext(DbContextOptions options) : base(options) 16 { 17 18 } 19 } 20 }
运行测试
通过以上步骤,主页面已经开发完成,点击运行进行测试,效果如下所示:
备注
本示例主要介绍学生信息管理系统的主页面开发,其他功能,后续继续更新,旨在抛砖引玉,一起学习,共同进步。
蝶恋花·欲减罗衣寒未去【作者】赵令畤
尽日沈香烟一缕。宿酒醒迟,恼破春情绪。远信还因归燕误。小屏风上西江路。