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. 动态创建 script 实现跨域请求数据

    动态创建script标签 (由事件触发) 在我们需要请求数据的时候我们就可以动态的创建 script 标签 src设置为我们需要请求数据的地址 另外我们可以附加参数 ?后面附加参数 例如 :?参数=1 ...

  2. SmartAdmin(SmartAdmin_v1.5.2)

    SmartAdmin_v1.5.2是一个基于bootstrap上开发的页面设置,前后台数据交互和样式显示. 用过的例子有F:\SmartAdmin_v1.5.2\SmartAdmin_v1.5.2\D ...

  3. C语言控制流语句

    title: 2017-10-18控制流 tags: binsearch else-if, shellsort, insertsort grammar_cjkRuby: true --- 前段时间忙着 ...

  4. 在PHP中,将一个汉字数组按照拼音首字母进行排序

    (之前发的这篇博文因为含有敏感关键字,只好重发一遍了) <?php $str = "我们可以在浏览器中看到,当鼠标移到元素上时,元素开始向右移动,开始比较慢,之后则比较快,移开时按原曲 ...

  5. 机器学习(二)-kNN手写数字识别

    一.kNN算法是机器学习的入门算法,其中不涉及训练,主要思想是计算待测点和参照点的距离,选取距离较近的参照点的类别作为待测点的的类别. 1,距离可以是欧式距离,夹角余弦距离等等. 2,k值不能选择太大 ...

  6. Java URL类踩坑指南

    背景介绍 最近再做一个RSS阅读工具给自己用,其中一个环节是从服务器端获取一个包含了RSS源列表的json文件,再根据这个json文件下载.解析RSS内容.核心代码如下: class Presente ...

  7. 微信小程序支付及退款流程详解

    微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端 ...

  8. Web App适配iPhoneX

    前言 Iphone每次退出新尺寸的手机都会掀起一番适配风波,这次没有下巴但有刘海的iPhoneX更是如此,网传横屏下的适配动画更是令不少人汗颜. 其实对于Native App来说,适配并不算困难(当然 ...

  9. redis在spring-boot中的应用

    Redis(REmote DIctionary Server) 是一个由Salvatore Sanfilippo写的key-value存储系统.Redis是一个开源的使用ANSI C语言编写.遵守BS ...

  10. codeforces 887A Div. 64 思维 模拟

    A. Div. 64 time limit per test 1 second memory limit per test 256 megabytes input standard input out ...