ABP框架中的Navigation功能用于管理业务系统中所有可用的菜单导航控件,通常在业务系统的首页会有一个全局性的导航菜单,JD商城,天猫,猪八戒网莫不如是。所以为方便起见,Navigation功能默认定义了一个"MainMenu"菜单添加到缓存字典中。该Navigation功能与普通ERP项目中可定制动态生成的导航菜单最大的区别应该是每一个菜单定义(MenuItemDefinition)可以设置一个权限只有用户拥有权限才会显示给该用户,控制更加的细更加的松耦合不是直接绑定到某个用户上。

  整体而言,Navigation分为两部分,第一部分是菜单定义部分,业务系统中所有可用菜单项的定义都会存储其中,第二部分是用户导向,是面向具体用户返回具体菜单信息,就是根据用户自身的权限过滤出一部分菜单定义项(MenuItemDefinition)并转换成UserMenuItem返回给用户。

  1.菜单定义

  菜单定义主要是MenuDefinition和MenuItemDefinition两类。前者代表一个菜单,会拥有一个MenuItemDefinition的集合表示所拥有的菜单选项,每一个MenuItemDefinition自身还会拥有子MenuItemDefinition的集合。

  业务项目开发者定义一个菜单的操作与上篇Feature的定义方式基本相同,定义一个集成自NavigationProvider的子类重写SetNavigation方法,在方法体中通过引用到的单例INavigationManager,注册进INavigationManager所拥有的一个缓存字典中,具体实例如下:

public class MyNavigationProvider1 : NavigationProvider
{
public override void SetNavigation(INavigationProviderContext context)
{
context.Manager.MainMenu.AddItem(
new MenuItemDefinition(
"Abp.Zero.Administration",
new FixedLocalizableString("Administration"),
"fa fa-asterisk",
requiresAuthentication: true
).AddItem(
new MenuItemDefinition(
"Abp.Zero.Administration.User",
new FixedLocalizableString("User management"),
"fa fa-users",
"#/admin/users",
requiredPermissionName: "Abp.Zero.UserManagement",
customData: "A simple test data"
)
).AddItem(
new MenuItemDefinition(
"Abp.Zero.Administration.Role",
new FixedLocalizableString("Role management"),
"fa fa-star-o",
"#/admin/roles",
requiredPermissionName: "Abp.Zero.RoleManagement"
)
)
);
}
}

在自定义的AbpModule中通过NavigationConfiguration注册到Providers属性中,而NavigationManager的Initialize方法会获取NavigationConfiguration的Providers逐个调用SetNavigation,完成整个菜单导航的注册。

  2.用户菜单

  真正会被用作菜单数据的用户菜单也有UserMenu和UserMenuItem两个类和上面的MenuDefinition和MenuItemDefinition是对应的,单例的UserNavigationManager提供了两个方法GetMenuAsync,GetMenusAsync,分别可以根据菜单导航名返回导航数据和根据用户Id,返回该用户所拥有的所有导航菜单。

  在GetMenuAsync,GetMenusAsync中会先获取全部的菜单定义项,根据定义项中是否拥有权限控制,有的话就制返回满足权限的菜单项。具体的逻辑如下:

private async Task<int> FillUserMenuItems(int? tenantId, long? userId, IList<MenuItemDefinition> menuItemDefinitions, IList<UserMenuItem> userMenuItems)
{
var addedMenuItemCount = ; using (var featureDependencyContext = _iocResolver.ResolveAsDisposable<FeatureDependencyContext>())
{
featureDependencyContext.Object.TenantId = tenantId; foreach (var menuItemDefinition in menuItemDefinitions)
{
if (menuItemDefinition.RequiresAuthentication && !userId.HasValue)
{
continue;
} if (!string.IsNullOrEmpty(menuItemDefinition.RequiredPermissionName) && (!userId.HasValue || !(await PermissionChecker.IsGrantedAsync(userId.Value, menuItemDefinition.RequiredPermissionName))))
{
continue;
} if (menuItemDefinition.FeatureDependency != null &&
(AbpSession.MultiTenancySide == MultiTenancySides.Tenant || tenantId.HasValue) &&
!(await menuItemDefinition.FeatureDependency.IsSatisfiedAsync(featureDependencyContext.Object)))
{
continue;
} var userMenuItem = new UserMenuItem(menuItemDefinition, _localizationContext);
if (menuItemDefinition.IsLeaf || (await FillUserMenuItems(tenantId, userId, menuItemDefinition.Items, userMenuItem.Items)) > )
{
userMenuItems.Add(userMenuItem);
++addedMenuItemCount;
}
}
} return addedMenuItemCount;
}

用户菜单就是这么简单。

ABP框架详解(五)Navigation的更多相关文章

  1. ABP框架详解(三)Domain

    此处的Domain主要指Abp类库根目录下Domain文件夹.顾名思义该目录下是用来存放与领域实体,领域逻辑执行,存储,领域服务相关的内容. 1.Entities (1)为整个Abp框架后期开发的所有 ...

  2. ABP框架详解(八)动态ApiController的生成和访问机制

    在ABP框架中提供了一套动态生成ApiController的机制(依然支持原生ApiController的使用方式),虽然说是动态生成ApiController但是实际上并没有真正在启动程序的时候生成 ...

  3. ABP框架详解(七)Caching

    在ABP框架中存在一个缓存机制,使用ICache的继承类来存储最终需要缓存的数据,可以吧ICache看成一个字典对象,使用Key作为真实数据的具有唯一性的表示.使用上与字典对象完全相同,Get方法传递 ...

  4. ABP框架详解(四)Feature

    ABP框架中存在一个Feature的特性,功能和设计思路非常类似于框架中的Authorization功能,都是来控制用户是否能够继续操作某项功能,不同点在于Authorization默认是应用在IAp ...

  5. ABP框架详解(二)AbpKernelModule

    AbpKernelModule类是Abp框架自己的Module,它也跟所有其他的Module一样继承自AbpModule,重写PreInitialize,Initialize,PostInitiali ...

  6. ABP框架详解(一)ABPBootstrapper

    在ABP框架的AbpBootstrapper主要用于框架的基本配置的注册和初始化,在Web应用启动阶段实例化一个AbpBootstrapper并调用Initialize方法初始化,该类主要包含两个公有 ...

  7. ABP框架详解(六)Aspects

    这种AOP式的设计非常类似于Asp.net MVC和WebApi中过滤器(Filter)机制,感觉没有太多可讲述的,只能谈谈设计思路. 框架中AspectAttribute特性用于设置到需要被拦截的T ...

  8. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

  9. mina框架详解

     转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...

随机推荐

  1. Word论文写作如何实现公式居中、编号右对齐

    第一步:插入表格 在公式所在行居中插入一行三列的表格,具体操作为: a.设置行居中,快捷键Ctrl+E: b.插入->表格->3×1的表格: 2 第二步:修改表格属性 新插入的表格三列等宽 ...

  2. Linux 内核通知链随笔【中】

    关于内核通知链不像Netlink那样,既可以用于内核与用户空间的通信,还能用于内核不同子系统之间的通信,通知链只能用于内核不同子系统之间的通信.那么内核通知链到底是怎么工作的?我们如何才能用好通知链? ...

  3. 关于Linkedlist 和 ArrayDeque的讨论

    转自:http://blog.csdn.net/f2006116/article/details/51375470 其中:我们要讨论的LinkedList和ArrayDeque都是实现Deque接口, ...

  4. JWPlayer第一个例子

    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding= ...

  5. 快快快!27个提升效率的iOS开源库推荐

    文章来源:http://www.csdn.net/article/2015-07-21/2825264-27-ios-open-source-libraries/1 我热爱开源,更喜爱那些花费宝贵的业 ...

  6. ss

    110000北京120000天津130000河北140000山西150000内蒙古210000辽宁220000吉林230000黑龙江310000上海320000江苏330000浙江340000安徽35 ...

  7. dos2unix unix2dos

    实现windows和linux之间的文件自动转换,消除^M.

  8. echarts绘制甘特图

      在setoption之后添加这段代码: window.addEventListener('resize', function () { myChart.resize();   }); 图表就能随着 ...

  9. 【java】:通用小知识

    1.将String字符串放在最前面 为了防止偶发性的NullPointerException 异常,我们通常将String放置在equals()函数的左边来实现字符串比较,如下代码: // Bad i ...

  10. 【Mail】JavaMail介绍及发送邮件(一)

    JavaMail介绍 JavaMail是SUN提供给开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发类库,支持常用的邮件协议,如SMTP.POP3.IMAP,开发人员使用JavaMail ...