ABP入门系列目录——学习Abp框架之实操演练

完成了增删改查以及页面展示,这一节我们来为任务清单添加【导航菜单】。

在以往的项目中,大家可能会手动在layout页面中添加一个a标签来新增导航菜单,这也是一种方式,但是如果要针对不同用户不同权限决定是否显示某个菜单,那么直接在layout页面中去控制就不方便了。

不过,ABP已经为大家考虑了这一点,集成了通用的创建和显示菜单的方式。其主要代码集成在Abp.Application.Navigation命名空间下,相应源码在此

下面我们就来梳理下导航菜单是如何实现和使用。

一、如何使用Abp集成的导航菜单

针对我们的『任务清单』Deom,我们需要在导航栏上添加一个【Task List】的菜单入口。

1.打开web展现层,定位到App_Start/xxxNavigationProvider.cs。

    public class LearningMpaAbpNavigationProvider : NavigationProvider
{
public override void SetNavigation(INavigationProviderContext context)
{
context.Manager.MainMenu
.AddItem(
new MenuItemDefinition(
"Home",
L("HomePage"),
url: "",
icon: "fa fa-home",
requiresAuthentication: true
)
).AddItem(
new MenuItemDefinition(
"Tenants",
L("Tenants"),
url: "Tenants",
icon: "fa fa-globe",
requiredPermissionName: PermissionNames.Pages_Tenants
)
).AddItem(
new MenuItemDefinition(
"Users",
L("Users"),
url: "Users",
icon: "fa fa-users",
requiredPermissionName: PermissionNames.Pages_Users
)
).AddItem(
new MenuItemDefinition(
"About",
L("About"),
url: "About",
icon: "fa fa-info"
)
);
}
}

该文件中默认定义了Home、Tenants、Users、About四个菜单。注意观察的话,想必会注意到Home菜单设置了requiresAuthentication: true,即只有登陆后才会显示该菜单。Tenants和Users菜单设置了requiredPermissionName属性,即用户具有指定的权限时才显示菜单。About菜单没有限制,默认显示。

每一个菜单项都是一个MenuItemDefinition,其中主要包括Name(唯一名称),DisplayName(本地化显示名称),Url(菜单跳转),Icon(指定菜单图标)。

解释到这里,大家自己都可以依葫芦画瓢,新增菜单了。

2.添加[Task List]菜单项

AddItem(
new MenuItemDefinition(
"TaskList",
L("Task List"),
url: "Tasks/Index",
icon: "fa fa-tasks",
requiresAuthentication: true
)

保存,刷新页面即可看到新增的[Task List]菜单了。

PS:之所以页面上会显示为[Task List],是因为我们并没有维护本地化资源文件。在对应的本地化配置文件中新增名为"Task List"的即可。比如在中文的本地化文件中添加

<text name="Task List" value="任务清单" />,重新启站点,将语言切换为中文。


二、Abp集成的导航菜单的代码结构

1.先来看看相关代码的类型依赖关系图



分析发现,abp集成的导航菜单实际上是应用了组合设计模式。

其中MenuDefinition为根节点,MenuItemDefinition为树枝节点,其中MenuItemDefinition中也维护了一个List的集合,当集合为空时,MenuItemDefinition即为树叶节点。

2.从图中可以看出,主要是由以下几部分组成:

  • MenuDefinition/MenuItemDefinition:菜单/菜单项定义。其中菜单项包括Name(唯一名称),DisplayName(本地化显示名称),Url(菜单跳转),Icon(指定菜单图标)。此外,可以通过指定RequiresAuthentication=true来限制菜单项只有对登录用户可见,同时也可以指定RequiredPermissionName来限定当用户有某个权限时菜单才可见。
  • UserMenu/UserMenuItem:封装了用于显示给用户的菜单/子菜单集合。
  • INavigationConfiguration/NavigationConfiguration:导航配置,维护了NavigationProvider的列表。
  • NavigationProvider:Provider模式(将api的定义和实现分离)。抽象类,定义了SetNavigation方法,在需要设置导航的项目中实现该类,并在对应的模块中PreInitialize方法中注册***NavigationProvider的实现。
  • INavigationManager/NavigationManager:其中接口中定义了一个Dictionary,用来存储应用程序中定义的所有菜单项,和一个MainMenu。注入了对INavigationConfiguration的引用,以便在NavigationManager中的Initialize方法遍历INavigationConfiguration配置的NavigationProvider列表进行菜单的初始化。

    IUserNavigationManager/UserNavigationManager:是对NavigationManager的一次封装。其中接口中定义了GetMenuAsync的重载方法,用来获取指定用户的菜单。
  • INavigationProviderContext/NavigationProviderContext:封装了INavigationManager的上下文类,用于传参。

三、Abp集成的导航菜单的具体实现

核心逻辑:NavigationManager遍历NavigationConfiguration中维护的NavigationProvider列表,并调用NavigationProvider实现的SetNavigation方法来完成导航菜单的初始化。

NavigationManager负责初始化菜单

NavigationConfiguration负责维护NavigationProvider的实现列表。

具体的NavigationProvider的实现

在对应的模块中注册具体的NavigtionProvider到INavigationConfiguration维护的列表中。

UserNavigationManager对NavigationManager进行了进一步的封装,根据用户和权限去创建和获取菜单。

在LayoutController中,通过注入对IUserNavigationManager的引用,来获取菜单,并由_TopMenu分部页进行最终呈现。

public class LayoutController : LearningMpaAbpControllerBase
{
private readonly IUserNavigationManager _userNavigationManager;
private readonly ISessionAppService _sessionAppService;
private readonly IMultiTenancyConfig _multiTenancyConfig;
private readonly ILanguageManager _languageManager; public LayoutController(
IUserNavigationManager userNavigationManager,
ISessionAppService sessionAppService,
IMultiTenancyConfig multiTenancyConfig,
ILanguageManager languageManager)
{
_userNavigationManager = userNavigationManager;
_sessionAppService = sessionAppService;
_multiTenancyConfig = multiTenancyConfig;
_languageManager = languageManager;
} [ChildActionOnly]
public PartialViewResult TopMenu(string activeMenu = "")
{
var model = new TopMenuViewModel
{
MainMenu = AsyncHelper.RunSync(() => _userNavigationManager.GetMenuAsync("MainMenu", AbpSession.ToUserIdentifier())),
ActiveMenuItemName = activeMenu
}; return PartialView("_TopMenu", model);
}
}

至此,我们完成了对导航菜单的梳理和总结。

ABP入门系列(6)——定义导航菜单的更多相关文章

  1. ABP入门系列(4)——领域层定义仓储并实现

    一.先来介绍下仓储 仓储(Repository): 仓储用来操作数据库进行数据存取.仓储接口在领域层定义,而仓储的实现类应该写在基础设施层. 在ABP中,仓储类要实现IRepository接口,接口定 ...

  2. ABP入门系列(3)——领域层定义仓储并实现

    ABP入门系列目录--学习Abp框架之实操演练 一.先来介绍下仓储 仓储(Repository): 仓储用来操作数据库进行数据存取.仓储接口在领域层定义,而仓储的实现类应该写在基础设施层. 在ABP中 ...

  3. ABP入门系列目录——学习Abp框架之实操演练

    ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WE ...

  4. ABP入门系列(3)——领域层创建实体

    这一节我们主要和领域层打交道.首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应.网上有代码生成器去简化我们这一步的任务,但是不建议初学者去使用. 一.首先来看看ABP体系结构 领域层就 ...

  5. ABP入门系列(2)——领域层创建实体

    ABP入门系列目录--学习Abp框架之实操演练 这一节我们主要和领域层打交道.首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应.网上有代码生成器去简化我们这一步的任务,但是不建议初学者 ...

  6. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  7. ABP入门系列(6)——展现层实现增删改查

    这一章节将通过完善Controller.View.ViewModel,来实现展现层的增删改查.最终实现效果如下图: 一.定义Controller ABP对ASP.NET MVC Controllers ...

  8. ABP入门系列(5)——创建应用服务

    一.解释下应用服务层 应用服务用于将领域(业务)逻辑暴露给展现层.展现层通过传入DTO(数据传输对象)参数来调用应用服务,而应用服务通过领域对象来执行相应的业务逻辑并且将DTO返回给展现层.因此,展现 ...

  9. ABP入门系列(7)——分页实现

    ABP入门系列目录--学习Abp框架之实操演练 完成了任务清单的增删改查,咱们来讲一讲必不可少的的分页功能. 首先很庆幸ABP已经帮我们封装了分页实现,实在是贴心啊. 来来来,这一节咱们就来捋一捋如何 ...

随机推荐

  1. 从零开始搭建Vue组件库 VV-UI

    前言: 前端组件化是当今热议的话题之一,也是我们在开发单页应用经常会碰到的一个问题,现在我们有了功能非常完善的Element-UI.各个大厂也相继宣布开源XXX-UI.但是也会存在一些问题,比如每个公 ...

  2. SQL命令语句进行大数据查询如何进行优化

    SQL 大数据查询如何进行优化? 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索 2.应尽量避免在 where 子句中对字段进行 null 值 ...

  3. 【YFMemoryLeakDetector】人人都能理解的 iOS 内存泄露检测工具类

    背景 即使到今天,iOS 应用的内存泄露检测,仍然是一个很重要的主题.我在一年前,项目中随手写过一个简单的工具类,当时的确解决了大问题.视图和控制器相关的内存泄露,几乎都不存在了.后来想着一直就那个工 ...

  4. SQL Server 基本操作之三种增加法

    前言: 数据库操作避免不了对数据的操作,操作方法大同小异,万变不离其宗,今就写一下各种花式操作的根本增删改查四种操作,今天我们就来说一下增加操作的三种方法 正文: 增加操作是对数据库进行数据行的添加, ...

  5. mysql数据库表卡死解决方法

    ---恢复内容开始--- 问题引起原因: 由于在执行大量插入操作的时候意外终止程序之后, MySQl的线程并没有被终止,导致表不能打开和操作 -  解决思路就是找到等待的线程并kill -- 查看所有 ...

  6. [DP]P2890 [USACO07OPEN]便宜的回文Cheapest Palindrome

    题目翻译(借鉴自@ 神犇的蒟蒻) [问题描述] 追踪每头奶牛的去向是一件棘手的任务,为此农夫约翰安装了一套自动系统.他在每头牛身 上安装了一个电子身份标签,当奶牛通过扫描器的时候,系统可以读取奶牛的身 ...

  7. GItCandy版本库搬迁步骤

    1.编译GitCandy,源码地址http://git.newlifex.com/NewLife/GitCandy 2.发布网站到文件夹 3.git网站停止运行 4.拷贝发布的网站到服务器目录&quo ...

  8. Asp.Net MVC 捆绑(Bundle)

    Asp.Net MVC 捆绑(Bundle) 大多数浏览器会对同一域名的请求限制请求数量,一般是在8个以内.每次最多可以同时请求8个,要是资源多于8个,那么剩下的就要排队等待请求了.所以为了提高首次加 ...

  9. c语言的数组

    1. 数组的基本概念 一个int类型的变量能保存一个人的年龄,如果想保存整个班的年龄呢? 1. 什么是数组 数组,从字面上看,就是一组数据的意思,没错,数组就是用来存储一组数据的 2. 数组的特点 ● ...

  10. 14. 监视ZooKeeper实例

    ZooKeeper服务可以通过以下两种方式进行监控: 使用一组四个字母的单词命令来监视健康状态 使用ZooKeeper内置的Java管理扩展功能 四个字母的单词命令 ZooKeeper响应一组命令,每 ...