.Net core 2.0 利用Attribute获取MVC Action来生成菜单
最近在学习.net core的同时将老师的MVC5项目中的模块搬过来用,其中有一块就是利用Attribute来生成菜单。
一·首先定义Action实体
/// <summary>
/// Action
/// </summary>
public class Action
{
/// <summary>
/// ActionId
/// </summary>
[DisplayName("ActionId")]
public Guid Id { get; set; }
/// <summary>
/// 唯一的名称
/// </summary>
[DisplayName("唯一的名称")]
public string Name { get; set; }
/// <summary>
/// 分区
/// </summary>
[DisplayName("分区")]
public string AreaName { get; set; }
/// <summary>
/// 控制器
/// </summary>
[DisplayName("控制器")]
public string ControllerName { get; set; }
/// <summary>
/// 活动
/// </summary>
[DisplayName("活动")]
public string ActionName { get; set; }
/// <summary>
/// 参数
/// </summary>
[DisplayName("参数")]
public string Parameter { get; set; }
/// <summary>
/// 文字
/// </summary>
[DisplayName("文字")]
public string Text { get; set; }
/// <summary>
/// 叶节点
/// </summary>
[DisplayName("叶节点")]
public bool IsLeaf { get; set; }
/// <summary>
/// 显示顺序
/// </summary>
[DisplayName("显示顺序")]
public int Ordinal { get; set; }
/// <summary>
/// 是否显示在左侧的导航栏中
/// </summary>
[DisplayName("是否显示在左侧的导航栏中")]
public bool ShowInLeftNavigationBar { get; set; }
/// <summary>
/// 图标
/// </summary>
[DisplayName("图标")]
public string IconClass { get; set; }
/// <summary>
/// 级次
/// </summary>
[DisplayName("级次")]
public int Depth { get; set; }
/// <summary>
/// 是否链接
/// </summary>
[DisplayName("是否链接")]
public bool IsLink { get; set; }
/// <summary>
/// 上级名称(采用上级名称而非上级Id是为了方便数据的存入)
/// </summary>
[DisplayName("上级名称")]
public string ParentName { get; set; }
/// <summary>
/// 限制角色
/// </summary>
[DisplayName("限制角色")]
public string AllowedRoles { get; set; } }
二.新建Attribute类
/// <summary>
/// 方法描述
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class ActionDescriptorAttribute : Attribute
{/// <summary>
/// 方法描述
/// </summary>
/// <param name="name">名称(必须唯一)</param>
/// <param name="text">标题</param>
/// <param name="depth">深度</param>
/// <param name="ordinal">显示顺序</param>
/// <param name="isLink">是否显示为链接</param>
/// <param name="showInLeftNavigationBar">是否显示在左侧的导航栏中</param>
public ActionDescriptorAttribute(string name, string text, bool isLink, int depth)
{
this.Name = name;
this.Text = text;
this.IsLink = isLink;
this.Depth = depth;
this.IsLeaf = true;
this.ShowInLeftNavigationBar = true;
this.Ordinal = ;
}
/// <summary>
/// 名称(必须唯一)
/// </summary>
public string Name { get; set; }
/// <summary>
/// 显示的文本
/// </summary>
public string Text { get; set; } /// <summary>
/// 图标
/// </summary>
public string IconClass { get; set; } /// <summary>
/// 参数
/// </summary>
public string Parameter { get; set; } /// <summary>
/// 是否子菜单
/// </summary>
public bool IsLeaf { get; set; } /// <summary>
/// 显示顺序
/// </summary>
public int Ordinal { get; set; } /// <summary>
/// 是否在左边导航栏显示
/// </summary>
public bool ShowInLeftNavigationBar { get; set; } /// <summary>
/// 一级菜单,该值为1,二级菜单,该值为2,依次类推
/// </summary>
public int Depth { get; set; }
/// <summary>
/// 是否链接
/// </summary>
public bool IsLink { get; set; }
/// <summary>
/// 上级名称
/// </summary>
public string ParentName { get; set; }
}
三.新建ActionsConfig类
public class ActionsConfig
{
/// <summary>
/// 是否生成Actions
/// </summary>
public static bool GenerateConfigs { get; set; }
/// <summary>
/// 是否采用追加模式,如果是追加模式则不删除现有数据
/// </summary>
public static bool IsAppendMode { get; set; }
/// <summary>
/// 是否更新现有记录
/// </summary>
public static bool IsModifed { get; set; }
public static Task<int> GetActions(string[] namespaces)
{
if (!GenerateConfigs) return new Task<int>(() => );
DAL.NoteBookContext db = new DAL.NoteBookContext();
var types = Assembly.GetExecutingAssembly().GetExportedTypes().Where(t => namespaces.Contains(t.Namespace)).ToArray();
var actions = new List<DAL.Entities.Action>();
for (int i = ; i < types.Length; i++)
{
bool isMvcController = types[i].IsSubclassOf(typeof(Controller));
//bool isApiController = types[i].IsSubclassOf(typeof(ApiController));
//if (!isMvcController && !isApiController) continue;
var fullName = types[i].FullName;
var name = types[i].Name;
var areaName = GetAreaName(fullName);
var tAttr = types[i].GetCustomAttribute<Attributes.ActionDescriptorAttribute>();
var authorize = types[i].GetCustomAttributes<AuthorizeAttribute>();
string roles = "";
if (authorize != null)
roles = string.Join(",", authorize.Select(a => a.Roles));
if (null != tAttr)
{
string attrName = tAttr.Name;
//如果是追加模式需要判断是否已经存在
bool find = db.Actions.Where(a => a.Name == attrName).Count() > ;
if (!IsAppendMode || !find)
actions.Add(new DAL.Entities.Action
{
Id = Guid.NewGuid(),
Name = tAttr.Name,
Text = tAttr.Text,
Parameter = tAttr.Parameter,
AreaName = areaName,
ControllerName = name.Substring(, name.IndexOf("Controller")),
ActionName = "#",
IsLeaf = tAttr.IsLeaf,
IconClass = tAttr.IconClass,
Ordinal = tAttr.Ordinal,
ShowInLeftNavigationBar = true,
Depth = tAttr.Depth,
ParentName = tAttr.ParentName,
IsLink = tAttr.IsLink,
AllowedRoles = roles
});
if (find && IsModifed)
{
DAL.Entities.Action action = db.Actions.Where(a => a.Name == attrName).FirstOrDefault();
action.Text = tAttr.Text;
action.Parameter = tAttr.Parameter;
action.AreaName = areaName;
action.ControllerName = name.Substring(, name.IndexOf("Controller"));
action.ActionName = "#";
action.IsLeaf = tAttr.IsLeaf;
action.IconClass = tAttr.IconClass;
action.Ordinal = tAttr.Ordinal;
action.ShowInLeftNavigationBar = true;
action.Depth = tAttr.Depth;
action.ParentName = tAttr.ParentName;
action.IsLink = tAttr.IsLink;
action.AllowedRoles = string.IsNullOrEmpty(roles) || roles == "None" ? null : roles;
if (string.IsNullOrEmpty(roles) || roles == "None")
action.AllowedRoles = null;
db.SaveChanges();
}
}
var methods = types[i].GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
for (int j = ; j < methods.Length; j++)
{
var mAttr = methods[j].GetCustomAttribute<Attributes.ActionDescriptorAttribute>();
if (null != mAttr)
{
string attrName = mAttr.Name;
//如果是追加模式需要判断是否已经存在
bool find = db.Actions.Where(a => a.Name == attrName).Count() > ;
if (find && IsModifed)
{
DAL.Entities.Action action = db.Actions.Where(a => a.Name == attrName).FirstOrDefault();
action.Text = mAttr.Text;
action.Parameter = mAttr.Parameter;
action.AreaName = areaName;
action.ControllerName = name.Substring(, name.IndexOf("Controller"));
action.ActionName = methods[j].Name;
action.IsLeaf = mAttr.IsLeaf;
action.IconClass = mAttr.IconClass;
action.Ordinal = mAttr.Ordinal;
action.ShowInLeftNavigationBar = mAttr.ShowInLeftNavigationBar;
action.Depth = mAttr.Depth;
action.ParentName = mAttr.ParentName;
action.IsLink = mAttr.IsLink;
action.AllowedRoles = string.IsNullOrEmpty(roles) || roles == "None" ? null : roles;
if (string.IsNullOrEmpty(roles) || roles == "None")
action.AllowedRoles = null;
db.SaveChanges();
}
if (find && IsAppendMode) continue;
actions.Add(new DAL.Entities.Action
{
Id = Guid.NewGuid(),
Name = mAttr.Name,
Text = mAttr.Text,
Parameter = mAttr.Parameter,
AreaName = areaName,
ControllerName = name.Substring(, name.IndexOf("Controller")),
ActionName = methods[j].Name,
IsLeaf = mAttr.IsLeaf,
IconClass = mAttr.IconClass,
Ordinal = mAttr.Ordinal,
ShowInLeftNavigationBar = mAttr.ShowInLeftNavigationBar,
Depth = mAttr.Depth,
ParentName = mAttr.ParentName,
IsLink = mAttr.IsLink,
AllowedRoles = roles
});
}
}
} var bll = new NoteBookBLL<DAL.Entities.Action>();
if (IsAppendMode)
return bll.AddRangeAsync(actions);
else
return bll.DeleteAsync(a => true).ContinueWith(task =>
{
return bll.AddRangeAsync(actions).Result;
});
} private static string GetAreaName(string fullName)
{
string[] nameSections = fullName.Split(new char[] { '.' });
var areaIndex = Array.IndexOf(nameSections, "Areas", );
string areaName = null;
if (areaIndex > )
areaName = nameSections[areaIndex + ];
return areaName;
}
}
四.在StartUp中调用,项目启动时执行方法。
public Startup(IConfiguration configuration)
{
Configuration = configuration;
ActionsConfig.GenerateConfigs = true;
//是否采用追加模式
ActionsConfig.IsAppendMode = true;
//是否修改现有记录
ActionsConfig.IsModifed = true;
ActionsConfig.GetActions(new string[] {
"xxx.Controllers"});
}
五.应用。只需在控制器上添加Attribute属性,就可以把相应的控制器加入到Action表中。

结果如图

萌新菜鸟,水平有限,此代码借鉴了我的老师的项目中的代码。欢迎各位大佬,批评指正,不吝赐教。
QQ:1051599574
邮箱:zhangjunx6497@163.com
.Net core 2.0 利用Attribute获取MVC Action来生成菜单的更多相关文章
- NET Core 2.0利用MassTransit集成RabbitMQ
NET Core 2.0利用MassTransit集成RabbitMQ https://www.cnblogs.com/Andre/p/9579764.html 在ASP.NET Core上利用Mas ...
- [转帖]2016年时的新闻:ASP.NET Core 1.0、ASP.NET MVC Core 1.0和Entity Framework Core 1.0
ASP.NET Core 1.0.ASP.NET MVC Core 1.0和Entity Framework Core 1.0 http://www.cnblogs.com/webapi/p/5673 ...
- ASP.NET Core 1.0、ASP.NET MVC Core 1.0和Entity Framework Core 1.0
ASP.NET 5.0 将改名为 ASP.NET Core 1.0 ASP.NET MVC 6 将改名为 ASP.NET MVC Core 1.0 Entity Framework 7.0 将 ...
- MVC4.0 利用IActionFilter实现单一Action返回多种结果
延续MVC4.0 实现单一Action返回多种结果,我们实现了在一个Action中根据前台请求方式的不同和请求内容的不同返回了多个结果,但是这种返回多个结果的业务逻辑并不通用.如果现在年纪Action ...
- 利用反射获取数据列+emit生成属性+单例模式
1:IDictionary<string,string > 可以存储数据,将拼接的sql可以存储到这里下次可以使用 定义自定义属性表和列 typeof(T).GetCustomAttrib ...
- 【原生态跨平台:ASP.NET Core 1.0(非Mono)在 Ubuntu 14.04 服务器上一对一的配置实现-篇幅1】
鸡冻人心的2016,微软高产年. build 2016后 各种干货层出不穷. 1 Win10 集成了bash ,实现了纳德拉的成诺,Microsoft Love Linux!!! 2 跨平台 ,收 ...
- ASP.NET Core 2.0 支付宝当面付之扫码支付
前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等.我本人是很喜欢.net的,并 ...
- Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core
本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core --- ...
- ASP.NET Core 实战:将 .NET Core 2.0 项目升级到 .NET Core 2.1
一.前言 最近一两个星期,加班,然后回去后弄自己的博客,把自己的电脑从 Windows 10 改到 Ubuntu 18.10 又弄回 Windows 10,原本计划的学习 Vue 中生命周期的相关知 ...
随机推荐
- hdu6351 Beautiful Now (全排列+循环节)
题目传送门 题意: 给你n和k,你每次能交换n的两个位,问最多k次后的最小和最大值 思路: 考虑到n到1e9,所以可以用全排列来暴力,但是我们不能全排列之前的数位, 因为n中的位数可能相等,那样很难计 ...
- vue路由守卫配合权限,白名单
router.beforeEach(async(to, from, next) => { // 进度条开始 NProgress.start() // 确认用户是否已登录(获取它的token值,这 ...
- ASE Alpha Sprint - backend scrum 9
本次scrum于2019.11.14再sky garden进行,持续15分钟. 参与人: Xin Kang, Zhikai Chen, Jia Ning, Hao Wang 请假: Lihao Ran ...
- mysql查询每个部门/班级前几名
Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id . +----+-------+--------+--------------+ | I ...
- [sqlmap源码阅读] 数据库识别
通过网页返回的数据库错误信息识别网站所有数据库类型,用到的正则表达式及支持识别的数据库类型,这些信息以xml文件的形式存在,使用 sax 解析xml.
- tpcc-mysql测试mysql5.6 (EXT4文件系统)
操作系统版本:CentOS release 6.5 (Final) 2.6.32-431.el6.x86_64 #1 内存:32G CPU:Intel(R) Xeon(R) CPU E5-2450 ...
- Apache HttpClient之fluent API的使用
该方法为Apache HttpClient 4.5以上的版本支持,在官网有明确的说明. 对比以前的方式,其优点是代码更简洁,同时为线程安全的.仅举一个最简单的post栗子 JAR包信息: <de ...
- 自定义日志注解 + AOP实现记录操作日志
需求:系统中经常需要记录员工的操作日志和用户的活动日志,简单的做法在每个需要的方法中进行日志保存操作, 但这样对业务代码入侵性太大,下面就结合AOP和自定义日志注解实现更方便的日志记录 首先看 ...
- LeetCode--051--N皇后(java)-star
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案. 每一种解 ...
- 【Java】JSONObject学习
介绍 JSONObject只是一种数据结构,可以理解为JSON格式的数据结构(key-value 结构),可以使用put方法给json对象添加元素.JSONObject可以很方便的转换成字符串,也可以 ...