最近在学习.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. D Makoto and a Blackboard

    Makoto and a Blackboard time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  2. C#学习——控件

    Windows应用程序控件的基类是位于System.Windows.Forms命名空间的Control类. Control类定义了控件类的共同属性.方法和事件,其他的控件类都直接或间接到派生自这个类. ...

  3. JS中类或对象的定义说明

    本篇文章主要是对JS中类或对象的定义进行说明介绍.我们知道,JS是面向对象的.谈到面向对象,就不可避免的要涉及类的概念.一般像c#,java这些强类型语言都有固定的定义类的语法.而JS的不同之处在于它 ...

  4. vue.js(14)--自定义全局指令

    <input type="text" class="form-control" v-model="keywords" v-focus& ...

  5. Perl脚本通过Expect登陆多台设备批量执行命令并Log

    本例子尝试使用Perl脚本借助Expect模块实现如下目的: 登陆多台设备 设备登陆信息按如下格式存放于文件中. $ cat hosts.txt 192.168.30.7:node1:telnet:b ...

  6. 7——C++类的使用

     定义了一个类之后,便可以如同用int.double等类型符声明简单变量一样,创建该类的对象,称为类的实例化.           类的定义实际上是定义了一种类型,类不接收或存储具体的值,只作为生成具 ...

  7. pwd 显示当前所在的工作路径

    1.功能说明 pwd命令是“print working directory ”首字母缩写,显示当前目录的绝对路径. 2.语法格式 pwd [option] pwd 选项 3.命令参数 参数 参数说明 ...

  8. AtCoder Beginner Contest 137

    前言 又是卡在了T4 , 总分 100 + 200 + 300 = 600pts rank 2449.以后还是要多积累比赛经验. A 输出a+b,a-b,a*b中最大的数,还要多简单?不挂代码了 B ...

  9. [php] phar

    build.php打包www目录: <?php class A{ public $a = 1; } $p = new Phar('test.phar',0,'test.phar'); $p-&g ...

  10. 企业级监控软件Zabbix搭建部署之zabbix在WEB页面中的配置

    企业级监控软件zabbix搭建部署之zabbix在WEB页面中的配置 企业级监控软件zabbix搭建部署之zabbix在WEB页面中的配置 关于安装请看 http://www.linuxidc.com ...