最近在学习.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来生成菜单的更多相关文章

  1. NET Core 2.0利用MassTransit集成RabbitMQ

    NET Core 2.0利用MassTransit集成RabbitMQ https://www.cnblogs.com/Andre/p/9579764.html 在ASP.NET Core上利用Mas ...

  2. [转帖]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 ...

  3. 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    将 ...

  4. MVC4.0 利用IActionFilter实现单一Action返回多种结果

    延续MVC4.0 实现单一Action返回多种结果,我们实现了在一个Action中根据前台请求方式的不同和请求内容的不同返回了多个结果,但是这种返回多个结果的业务逻辑并不通用.如果现在年纪Action ...

  5. 利用反射获取数据列+emit生成属性+单例模式

    1:IDictionary<string,string > 可以存储数据,将拼接的sql可以存储到这里下次可以使用 定义自定义属性表和列 typeof(T).GetCustomAttrib ...

  6. 【原生态跨平台:ASP.NET Core 1.0(非Mono)在 Ubuntu 14.04 服务器上一对一的配置实现-篇幅1】

    鸡冻人心的2016,微软高产年. build 2016后 各种干货层出不穷. 1 Win10 集成了bash  ,实现了纳德拉的成诺,Microsoft Love Linux!!! 2 跨平台  ,收 ...

  7. ASP.NET Core 2.0 支付宝当面付之扫码支付

    前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等.我本人是很喜欢.net的,并 ...

  8. Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core

    本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core --- ...

  9. ASP.NET Core 实战:将 .NET Core 2.0 项目升级到 .NET Core 2.1

    一.前言  最近一两个星期,加班,然后回去后弄自己的博客,把自己的电脑从 Windows 10 改到 Ubuntu 18.10 又弄回 Windows 10,原本计划的学习 Vue 中生命周期的相关知 ...

随机推荐

  1. js数组中的引用类型

    我们看一下这个例子: let a={tile:'深复制'}; let b=a; a.title='浅复制'; 那么我们会获得两个对象,一个a,一个b,a的title是浅复制,b的title是深复制.但 ...

  2. SSM商城系统开发笔记-问题01-通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明。

    配置搭建完后进行Post请求测试时报错: Caused by: org.xml.sax.SAXParseException; lineNumber: 14; columnNumber: 29; cvc ...

  3. asp.net core2.1认证和授权解密

    来源:https://www.cnblogs.com/pangjianxin/p/9372562.html asp.net core2.1认证和授权解密 本篇文章翻译自:https://digital ...

  4. AspNetCore使用MySQL

    既然NetCore开源,那么也使用开源的MySQL的数据库呢?当然NetCore不止单单配MSSQL数据库而已.今天我来讲解NetCore怎么使用MySQL进行开发. 首先新建一个NetCore项目 ...

  5. echart 折线渐变 加柱形图结合图形,左右纵轴自设置格式,现行图北京渐变 ,x轴字体倾斜

    app.title = '折柱混合'; option = { grid: { left: '5%', //距离左边的距离 right: '5%', //距离右边的距离 top:'8%', bottom ...

  6. [好好学习]在VMware中安装Oracle Enterprise Linux (v5.7) - (4/5)

  7. Windows电脑无法识别USB设备怎么办?

    您可能已经注意到,如果您使用USB设备并将其插入计算机,Windows会识别并配置它.然后,如果你拔掉它并将其重新插入另一个USB端口,Windows就会出现一连串的健忘症,并认为这是一个完全不同的设 ...

  8. LOJ 2840「JOISC 2018 Day 4」糖

    有趣的脑子题(可惜我没有脑子 好像也可以称为模拟费用流(? 我们考虑用链表维护这个东西 再把贡献扔到堆里贪心就好了 大概就是类似于有反悔机制的贪心?我们相当于把选中的一个打上一个-v的tag然后如果选 ...

  9. 阿里云ECS无法通过SSL远程链接问题。

    自己配置的SSL,通过密码,公司的是通过密钥,结果也是一样, 环境:centos7.x 网络: 家里宽带 公司网络 省图书馆wifi 家里宽带,公司网络均可以链接上去, 但唯独省图书馆wifi链接失败 ...

  10. vue中怎么使用vuex

    做一个简单的vuex如何使用的介绍: 先安装: npm i vuex --save-dev 新建一个store文件夹, 在store文件夹中建一个index.js文件,在该文件中:         i ...