0 Asp.Net Core 項目實戰之權限管理系統(0) 無中生有html
1 Asp.Net Core 項目實戰之權限管理系統(1) 使用AdminLTE搭建前端前端
2 Asp.Net Core 項目實戰之權限管理系統(2) 功能及實體設計git
3 Asp.Net Core 項目實戰之權限管理系統(3) 經過EntityFramework Core使用PostgreSQLgithub
4 Asp.Net Core 項目實戰之權限管理系統(4) 依賴注入、倉儲、服務的多項目分層實現session
5 Asp.Net Core 項目實戰之權限管理系統(5) 用戶登陸app
6 Asp.Net Core 項目實戰之權限管理系統(6) 功能管理異步
7 Asp.Net Core 項目實戰之權限管理系統(7) 組織機構、角色、用戶權限ide
8 Asp.Net Core 項目實戰之權限管理系統(8) 功能菜單的動態加載佈局
系統登陸後,會在session中記錄當前登陸用戶的信息。
//檢查用戶信息 var user = _userAppService.CheckUser(model.UserName, model.Password); if (user != null) { //記錄Session HttpContext.Session.SetString("CurrentUserId", user.Id.ToString()); HttpContext.Session.Set("CurrentUser", ByteConvertHelper.Object2Bytes(user)); //跳轉到系統首頁 return RedirectToAction("Index", "Home"); }
因爲一個用戶能夠擁有多個角色,咱們須要作的是,根據當前登陸用戶的Id,獲得其擁有的全部角色信息,而後取當前用戶全部角色擁有的功能權限求合集,獲得的就是當前登陸用戶所擁有的功能權限信息。
定義應用服務接口
在IMenuAppService中定義接口
/// <summary> /// 根據用戶獲取功能菜單 /// </summary> /// <param name="userId">用戶ID</param> /// <returns></returns> List<MenuDto> GetMenusByUser(Guid userId);
服務接口實現
在MenuAppService中實現接口
/// <summary> /// 根據用戶獲取功能菜單 /// </summary> /// <param name="userId">用戶ID</param> /// <returns></returns> public List<MenuDto> GetMenusByUser(Guid userId) { List<MenuDto> result = new List<MenuDto>(); var allMenus = _menuRepository.GetAllList(it=>it.Type == 0).OrderBy(it => it.SerialNumber); if (userId == Guid.Empty) //超級管理員 return Mapper.Map<List<MenuDto>>(allMenus); var user = _userRepository.GetWithRoles(userId); if (user == null) return result; var userRoles = user.UserRoles; List<Guid> menuIds = new List<Guid>(); foreach (var role in userRoles) { menuIds = menuIds.Union(_roleRepository.GetAllMenuListByRole(role.RoleId)).ToList(); } allMenus = allMenus.Where(it => menuIds.Contains(it.Id)).OrderBy(it => it.SerialNumber); return Mapper.Map<List<MenuDto>>(allMenus); }
在之前的Asp.net MVC中,咱們會常用@Html.Action來發起一個ChildAction請求,渲染並獲得一個分部視圖填充的主功能視圖中,以此來實現一些公用的或者是獨立的界面區域。在Asp.Net Core中,不在存在將以ViewComponent替代。
你能夠將View Component看作是一個mini的Controller——它只負責渲染一小部份內容,而非所有響應,全部分部視圖能解決的問題,你均可以使用View Component來解決,好比:動態導航菜單、Tag標籤、登陸窗口、購物車、最近閱讀文章等等。
ViewComponent建立很是簡單,只須要將咱們的類繼承自ViewComponent類就好了。每一個ViewComponent須要包括一個名稱爲Invoke的約定方法,你能夠在此方法中傳入你須要的任何參數,系統也支持InvokeAsync方法實現異步功能,此約定方法爲該ViewComponent的最終輸出出口。
在Fonour.MVC項目中新建一個名稱爲「Components」的文件夾,用來存放咱們全部的視圖組件類,在該文件夾下新建一個名稱爲NavigationViewComponent的組件。
[ViewComponent(Name = "Navigation")] public class NavigationViewComponent : ViewComponent { private readonly IMenuAppService _menuAppService; private readonly IUserAppService _userAppService; public NavigationViewComponent(IMenuAppService menuAppService, IUserAppService userAppService) { _menuAppService = menuAppService; _userAppService = userAppService; } public IViewComponentResult Invoke() { var userId = HttpContext.Session.GetString("CurrentUserId"); var menus = _menuAppService.GetMenusByUser(Guid.Parse(userId)); return View(menus); } }
上面實現的約定方法Invoke中,最後Return View(Menus),與咱們控制器中Action返回視圖的方法很類似。ViewComponent尋找視圖也是遵守約定的。他會自動從如下路徑去尋找對應的視圖文件。
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/Default.cshtml
對於某個具體功能對應的組件,咱們最好按照上面第一種路徑規則,把對應的視圖文件放在功能對應的Controller下面
對於系統級別的視圖組件,好比咱們如今要實現的左側功能導航菜單,建議按照第二種路徑規則,放在Views/Shared下面。
在Views/Shared文件夾下新建一個名稱爲Components的文件夾,而後在該文件夾下建立一個名稱爲「Navigation」的文件夾,注意這個文件夾名與咱們上面定義的組件名稱是要保持一直的。
在「Navigation」文件夾下建立一個名稱爲Default.cshtml的視圖頁。內容以下:
@model List<Fonour.Application.MenuApp.Dtos.MenuDto> <li class="header">權限管理</li> @foreach (var menu in Model) { var isActive = ViewBag.CurrentMenu == menu.Code; //判斷當前功能是否處於激活 <li class="@(isActive ? "active" : "")"><a href="@menu.Url"><i class="fa fa-link"></i> <span>@menu.Name</span></a></li> }
該視圖接受一個在咱們組件類中返回的菜單集合對象,並根據此菜單集合渲染咱們須要的菜單。咱們根據ViewBag.CurrentMenu是否等於當前菜單的編碼,來肯定該菜單是否屬於激活狀態,這樣能夠實現咱們單擊某個菜單界面刷新後,該功能菜單處於激活狀態。
基於此,咱們須要在每一個功能頁面指定ViewBag.CurrentMenu的值。如用戶管理功能,咱們在/Views/User/Index.cshtml頂部添加以下代碼便可。
@{
ViewBag.CurrentMenu = "User";
}
固然,若是你以爲這種硬編碼的方式你不喜歡,你能夠在菜單單擊的時候,把當前菜單對應的code值傳至服務端,由服務端在返回對應的視圖以前,指定ViewBag.CurrentMenu的值便可。
咱們修改佈局頁_Layout.cshtml中菜單加載部分的代碼,將寫死的功能菜單信息,修改成經過使用ViewComponent根據用戶Id動態加載功能菜單。
<ul class="sidebar-menu"> @await Component.InvokeAsync("Navigation"); @*<li class="treeview"> <a href="#"> <i class="fa fa-link"></i> <span>Multilevel</span> <span class="pull-right-container"> <i class="fa fa-angle-left pull-right"></i> </span> </a> <ul class="treeview-menu"> <li><a href="#">Link in level 2</a></li> <li><a href="#">Link in level 2</a></li> </ul> </li>*@ </ul>
此時咱們使用一個只分配了其中三個菜單權限的帳戶登陸系統,一切按照咱們預想的,能夠根據當前登陸用戶動態加載該用戶所擁有權限的功能菜單了,並且咱們進入某個功能後,頁面刷新後已經能夠自動把咱們進入的功能菜單設置爲激活狀態了。
本次主要學習了ViewComponent的使用,實現了功能菜單的動態加載。
最開始是本着本身學習的態度寫這個系列的,內容整體來講屬於基礎入門級的,到如今也算是基本功能都已經實現了,裏面有不少不足或不完善的地方,能夠根據須要進行調整吧。
從孩子出生,轉眼間到如今3個月了,天天熬夜熬的精疲力盡,工做上也是忙的不可開交,有些朋友給個人留言中的,我有空看到就回復了,有些朋友的問題,有可能我沒時間看到,也有可能實在抽不出時間去幫你找問題所在,還得麻煩您本身多動手實踐一下了,請見諒。