剖析如何在南茜中央银行使Swagger生成API文档起名

索引

前言

上一篇博客介绍了选择南希框架内部的章程来成立了二个粗略到不能再不难的Document。但是还有巨大的欠缺。

为了能稍微完善一下以此Document,那篇引用了如今盛行的Swagger,以及另一个开源的Nancy.Swagger花色来形成今日的任务!

注:Swagger是早已相对成熟的了,但Nancy(2.0.0-clinteastwood)和Nancy.Swagger(2.2.6-阿尔法)是依据近期的摩登版本,但日前的都以尚未发布正式版,所以三番五次API也许会有多少变化。

下边先来归纳看看哪些是Swagger

【无私分享:从入门到精晓ASP.NET MVC】从0早先,一起搭框架、做项目 目录索引

简述

今日大家来做权限的田管,这篇相比多 希望新手朋友慢慢消化

品类准备

我们用的工具是:VS 二零一一 + SqlServer 2011 + IIS7.5

可望大家对ASP.NET
MVC有三个从头的理解,理论性的事物大家不做过多解释,有个别地点不领悟也没涉及,会用就行了,用的多了,用的久了,自然就知道了。

花色始于

何为Swagger

The World's Most Popular Framework for APIs.那是Swagger官方的叙述。能表露是社会风气上最风靡的,也是要有必然资本的!

光看这几个描述就明白Swagger不会差!究竟人家敢如此说。当然个人也以为Swagger确实很科学。

透过合法文书档案,我们都清楚要想生成Swagger文书档案,可以选取YAML或JSON二种格局来书写,由于大家平常写程序用的可比多的是JSON!

之所以本文首假若应用了JSON,顺带说一下YAML的语法也是属于易懂易学的。

既然是用JSON书写,那么要怎么写吧?这么些实际上是有一套规定、约束,大家假如服从这一个来写就能够了。详细内容能够瞻仰OpenAPI
Specification

本文前边的剧情将默许园友们对Swagger有过摸底。

Swagger重要有上边多少个东西,要引用基本的体制温州扬剧本就不在多说了。

自然,引用样式黄岩乱弹本只是最宗旨的前提,上边那段js(来自swagger-ui项目)才是最为重要的!

<script>
window.onload = function() {
    // Build a system
    const ui = SwaggerUIBundle({
        url: "your url",//返回json数据的url地址
        dom_id: '#swagger-ui',//在这个div展示内容
        presets: [
            SwaggerUIBundle.presets.apis,
            SwaggerUIStandalonePreset
        ],
        plugins: [
            SwaggerUIBundle.plugins.DownloadUrl
        ],
        layout: "StandaloneLayout"
    })

    window.ui = ui
}
</script>

固然在地点加上注释的五个属性:url钦命了笔者们要来得数据(JSON格式)的发源,dom_id点名了在id为swagger-ui的器皿中显得大家的文书档案。

在加载的时候创立了Swagger相关的始末,主要的有上面包车型大巴几个,别的的用默许的就足以了。

回顾的话,大家恳请了这一个url获得了那么些json数据,再依据那些数据在dom_id中布局出我们所阅览标页面。有那么点数量驱动的情趣。

当然这么些JSON数据是有格式须求的。能够看看上边包车型的士简要示例

{
  "swagger": "2.0",
  "info": {
    "title": "Simple API overview",
    "version": "v2"
  },
  "paths": {
    "/": {
      "get": {
        "operationId": "listVersionsv2",
        "summary": "List API versions",
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 300 response",
            "examples": {
              "application/json": "一串json"
            }
          }
        }
      }
    }
  },
  "consumes": [
    "application/json"
  ]
}

那也就象征大家只要求严峻依照Swagger的定义,就足以生成二个即雅观,又可进行的API文书档案了。

越来越多相关JSON示例可参见

https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json

一 、新建权限控制器 继承 基础控制器

Nancy.Swagger说明

Nancy.Swagger是我们前几天的顶梁柱,是1个依照MIT协议的开源项目。Github地址:Nancy.Swagger

本来通过上边关于Swagger的印证,也早已大概知道了这一个类型主要为大家做了怎么样。便是结构Swgger所需求的JSON格式的多寡!

它并没有像Swashbuckle.AspNetCore一致集成了SwaggerUI的始末到项目中去,只是叁个提供数据的类型。

其合法的言传身教师职业道德姆o是用跳转到petstore.swagger.io措施来成功的。可是平时性是要等待非常长日子的,应该是互联网的难题。

为了制止这一动静,能够因此下边包车型大巴操作防止:

  • 手动下载swagger-ui相关的内容并添加到我们的新类型中。同时自个儿还将这几个设置成嵌入式的财富。

起名 1

  • 丰硕三个用以体现的页面,示例为doc.html,内容能够照搬swagger-ui目录下边包车型客车index.html

  • 在Bootstrapper中添加静态能源的引用

    protected override void ConfigureConventions(NancyConventions nancyConventions)
    {

    base.ConfigureConventions(nancyConventions);
    nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("swagger-ui"));
    

    }

  • 在走访大家API时,将其重定向到doc.html页面

    public class HomeModule : NancyModule
    {

    public HomeModule()
    {
        Get("/", _ =>
        {
            return Response.AsRedirect("/swagger-ui");     
        });
    
        Get("/swagger-ui",_=>
        {                            
            var url = $"{Request.Url.BasePath}/api-docs";
            return View["doc", url];
        });
    }
    

    }

  • 修改doc.html的始末,将上述的url,替换来@Model

    window.onload = function() {
    // Build a system
    const ui = SwaggerUIBundle({

    url: "@Model",
    dom_id: '#swagger-ui',
    presets: [
        SwaggerUIBundle.presets.apis,
        SwaggerUIStandalonePreset
    ],
    plugins: [
        SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
    

    })
    window.ui = ui
    }

成就地点的始末后,就初步布局我们的文书档案了。

① 、我们在Areas/SysManage/Controllers 下新建一个控制器 叫PermissionController

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace WebPage.Areas.SysManage.Controllers
 8 {
 9     public class PermissionController : Controller
10     {
11         // GET: SysManage/Permission
12         public ActionResult Index()
13         {
14             return View();
15         }
16     }
17 }

 

布局文书档案的为主音信

此间最重即使设置那些API文书档案的概要消息,比如文书档案的标题,此api的本子等

急需经过SwaggerMetadataProvider的SetInfo方法来安装那么些音讯

下边是现实性的言传身教代码,写在Bootstrapper中:

protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
    SwaggerMetadataProvider.SetInfo("Nancy Swagger Example", "v1.0", "Some open api", new Contact()
    {
        EmailAddress = "catcher_hwq@outlook.com",
        Name = "Catcher Wong",
        Url = "http://www.cnblogs.com/catcher1994"
    }, "http://www.cnblogs.com/catcher1994");

    base.ApplicationStartup(container, pipelines);
}

那儿对应的光景效果(这么些时候是不能够健康运作的,只是呈现了这部分的作用)如下:

起名 2

上边代码生成的JSON数据是符合规范的,如下所示:

起名 3

上面要做的正是组织路由有关的音信

贰 、大家让PermissionController 继承基础控制器 BaseController 那里须要加上引用 using WebPage.Controllers

起名 4

 

不带任何请求参数

先在Module中定义二个简短的路由,这几个路由不带任何参数。

Get("/", _ =>
{
    var list = new List<Product>
    {
        new Product{ Name="p1", Price=199 , IsActive = true },
        new Product{ Name="p2", Price=299 , IsActive= true }
    };

    return Negotiate.WithMediaRangeModel(new Nancy.Responses.Negotiation.MediaRange("application/json"), list);                
}, null, "GetProductList");

然后在MetadataModule中添加相应的叙述,那里的MetadataModule与上一篇是相似的,那也是为什么作者会在上一篇先介绍不行使

其三方组件的来组织的缘故,因为那种写法上面,两者没有实质的界别!

 Describe["GetProductList"] = desc => desc.AsSwagger(
    with => with.Operation(
        op => op.OperationId("GetProductList")
        .Tag("Products")
        .Summary("Get all products")
        .Response(r=>r.Schema<IEnumerable<Product>>().Description("OK"))
        .Description("This returns a list of products")
        ));

上边是一些Nancy.Swagger当中的宗旨内容,也是上一篇所没有的十分规之处。

AsSwagger是RouteDescription一个扩张方法,这些主意是再次来到大家须求的PathItem。

OperationId是其一路由的一个投机名称,源码里面包车型客车字段定义注明它要唯一。对越来越详细的讲述或许去看Swagger中对那一个参数的印证!

Tag能够知道为那一个路由属于分外分组,起分隔符的效率,举个例子,现在有A,B三个模块的API,大家肯定不可能把它们交叉排列下去

而是A的停放一个地点,B的三个地点,便于大家的的界别。

Summary是时下路由的简练描述,要低于11几个字符。

Description是方今路由的详细描述。

Response是意在的周转结果的连锁内容,能够有多个,那里没有标明状态码,而是一贯写处理的始末,此时验证那里用的是私下认可的状态码。

Response里面又是一个信托,里面又有一部分概念:

Schema标明当前响应应该回到的档次是怎样

Description是以此响应对应的叙说音信

本条时候是会出错的,因为我们在Respoonse的时候钦点了Schema,不过我们并没有点名它的概念。

咱俩供给先在MetadataModule中援引ISwaggerModelCatalog其一接口并调用它的AddModel主意把相关的档次丰裕进去,那样才能健康运营!

public ProductsMetadataModule(ISwaggerModelCatalog modelCatalog)
{
    //添加相应的类型
    modelCatalog.AddModels(typeof(Product), typeof(IEnumerable<Product>));

     Describe["GetProductList"] = desc => desc.AsSwagger(
        with => with.Operation(
            op =>
            op.OperationId("GetProductList")
            .Tag("Products")
            .Summary("Get all products")
            //在Schema中使用modelCatalog
            .Response(r => r.Schema<IEnumerable<Product>>(modelCatalog).Description("OK"))
            .Description("This returns a list of products")
            ));
}

演示结果如下:

先来探视上面安装相应的始末:

起名 5

点击Try it out运作的结果

起名 6

能够看出采取curl
去访问大家的骨子里接口得到服务器的响应新闻(结果和底部)

在极端履行一下以此命令,也是这么些结果。

起名 7

③ 、大家抬高必要的接口注解,那里须求加上引用 using Service.IService

 1  public class PermissionController : BaseController
 2     {
 3         #region 声明容器
 4         /// <summary>
 5         /// 系统管理
 6         /// </summary>
 7         ISystemManage SystemManage { get; set; }
 8         /// <summary>
 9         /// 权限管理
10         /// </summary>
11         IPermissionManage PermissionManage { get; set; }
12         /// <summary>
13         /// 模块管理
14         /// </summary>
15         IModuleManage ModuleManage { get; set; }
16         #endregion
17 
18         public ActionResult Index()
19         {
20             return View();
21         }
22     }

 

带Path参数和Query参数

同等的,先在Module中定义3个路由,那一个路由包括了几个Path参数和三个Query参数

Get("/{productid}", _ =>
{

    var productId = _.productid;

    if (string.IsNullOrWhiteSpace(productId))
    {
        return HttpStatusCode.NotFound;
    }

    var isActive = Request.Query.isActive ?? true;

    var product = new Product
    {
        Name = "apple",
        Price = 100,
        IsActive = isActive
    };

    return Negotiate.WithMediaRangeModel(new Nancy.Responses.Negotiation.MediaRange("application/json"), product);
}, null, "GetProductByProductId");

那里作了多或多或少操作,为的是演示尽也许多的用法。借使传递的出品id为空,则间接重返404。假设没有输入isActive这些Query参数

返回Productr的IsActive就为false。

下一场在MetadataModule中添加相应的讲述

Describe["GetProductByProductId"] = desc => desc.AsSwagger(
        with => with.Operation(
            op => op.OperationId("GetProductByProductId")
            .Tag("Products2")
            .Summary("Get a product by product's id")
            .Description("This returns a product's infomation by the special id")
            .Parameter(new Parameter
            {
                Name = "productid",
                In = ParameterIn.Path,//指明该参数是对应路由上面的同名参数
                Required = true,//必填
                Description = "id of a product"
            })
            .Parameter(new Parameter
            {
                Name = "isactive",
                In = ParameterIn.Query,//指明该参数是对应QueryString上面的参数
                Description = "get the actived product",
                Required = false//非必填
            })
            .Response(r => r.Schema<Product>(modelCatalog).Description("Here is the product"))
            .Response(404, r => r.Description("Can't find the product"))
            ));

此间多了2个Parameter是上边没有关联的,那几个正是咱们的哀告参数,这里的央浼参数包罗下边多样:

  • Path
  • Query
  • Body
  • Header
  • Form

下边是运作的效应图,分别演示了上面二种景况

  • 不填productid,不能够实施,输入框会变红
  • 填了productid,能履行,但是服务器端再次回到的isactive是false
  • 填了productid和isactive,能履行,服务器重返的isactive是true

起名 8

理所当然以往在MetadataModule的参数还有别的的写法

 Describe["GetProductByProductId"] = desc => desc.AsSwagger(
        with => with.Operation(
            op => op.OperationId("GetProductByProductId")
            .Tag("Products2")
            .Summary("Get a product by product's id")
            .Description("This returns a product's infomation by the special id")
            .Parameters(new List<Parameter>
            {
                new Parameter{Name = "productid",In = ParameterIn.Path,Required = true,Description = "id of a product"},
                new Parameter{Name = "isactive",In = ParameterIn.Query,Description = "get the actived product",Required = false}
            })
            .ProduceMimeType("application/json")
            .Response(r => r.Schema<Product>(modelCatalog).Description("Here is the product"))
            .Response(404, r => r.Description("Can't find the product"))
            ));

可以用Parameters一贯将有着的参数,组合成3个凑合来进展处理。

那时候的意义和地点是同一的。

④ 、千万不要遗忘  大家添加xml的注入配置 (Config/Controllers.xml)

起名 9

 

布局注入:

起名 10

 

完全代码:

起名 11起名 12

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <objects xmlns="http://www.springframework.net">
 3   <description>Spring注入控制器,容器指向Service层封装的接口</description>
 4   <!--系统管理 Begin-->
 5   <!--主页控制器-->
 6   <object type="WebPage.Areas.SysManage.Controllers.HomeController,WebPage" singleton="false">
 7     <property name="ModuleManage" ref="Service.Module"/>
 8   </object>
 9   <!--登录控制器-->
10   <object type="WebPage.Areas.SysManage.Controllers.AccountController,WebPage" singleton="false">
11     <property name="UserManage" ref="Service.User"/>
12   </object>
13   <!--模块管理-->
14   <object type="WebPage.Areas.SysManage.Controllers.ModuleController,WebPage" singleton="false">
15     <property name="ModuleManage" ref="Service.Module"/>
16     <property name="PermissionManage" ref="Service.Permission"/>
17     <property name="SystemManage" ref="Service.System"/>
18   </object>
19   <!--权限管理-->
20   <object type="WebPage.Areas.SysManage.Controllers.PermissionController,WebPage" singleton="false">
21     <property name="ModuleManage" ref="Service.Module"/>
22     <property name="SystemManage" ref="Service.System"/>
23     <property name="PermissionManage" ref="Service.Permission"/>
24   </object>
25   <!--系统管理 end-->
26 </objects>

View Code

 OK,那样 控制器和容器证明大家就达成了~

 

请求头参数和请求体参数

在Module中添加叁个剧增货物的艺术,这一个法子包罗三种请求参数,一种是例行POST的json格式的数量,一种是请求头,对于请求头,只是一口咬住不放了一晃客户端发起的伏乞有没有隐含相应的请求头正是了,并从未做严刻的论断。同时为了演示多样MIME类型的归来结果,那里十分了json和xml格式的回来结果。

Post("/", _ =>
{
    var product = this.Bind<Product>();

    if(!Request.Headers.Any(x=>x.Key=="test"))
    {
        return HttpStatusCode.BadRequest;
    }

    return Negotiate
        .WithMediaRangeModel(new Nancy.Responses.Negotiation.MediaRange("application/json"), product)
        .WithMediaRangeModel(new Nancy.Responses.Negotiation.MediaRange("application/xml"), product)
        ;
}, null, "AddProduct");

如出一辙的,MetadataModule中添加如下的叙说:

Describe["AddProduct"] = desc => desc.AsSwagger(
with => with.Operation(
    op => op.OperationId("AddProduct")
            .Tag("Products")
            .Summary("Add a new product to database")
            .Description("This returns the added product's infomation")
            .BodyParameter(para=>para.Name("para").Schema<Product>().Description("the infomation of the adding product").Build())//Request body
            .Parameter(new Parameter()
            {
                Name = "test",
                In = ParameterIn.Header,//http请求头
                Description = "must be not null",
                Required = true,
            })           
            .ConsumeMimeType("application/json") //post的参数只允许是json格式            
            .ProduceMimeTypes(new List<string>{ "application/json","application/xml" })//结果支持json和xml
            .Response(r => r.Schema<Product>(modelCatalog).Description("Here is the added product"))
            .Response(400, r => r.Description("Some errors occur during the processing"))
));

BodyParameter是我们在POST等操作时用的,它须要钦赐我们POST的数码格式(Schema那里的类型),为了演示添加请求头消息,所以那里也加了3个必填的伏乞头消息。

ConsumeMimeType意味着大家倡导呼吁的数码格式必须是json格式的,当然也得以援助种种区别的数额格式。

ProduceMimeTypes代表服务端响应时援助的数量格式,那里内定了json和Xml也是为了和我们Module中的内容相呼应。

示范效果:

起名 13

贰 、添加侧栏选拔

咱俩把权限管理的页面 分左右两栏
左栏是怀有的模块  右栏是权力

作用是那样的:

起名 14

 

标明过时API和一个API属于三个分组

神迹,API的尽头分的不是很清楚或然有交集的时候,恐怕会出现如此的情景:1个api会属于两个分组。

前面我们都以直接内定了四个tag,也就象征上面的只是对应二个tag。

先来定义贰个措施,用于演示多分组和过时、放任的API

Head("/",_=>
{
    return HttpStatusCode.OK;
},null,"HeadOfProduct");

Metadata内容

 Describe["HeadOfProduct"] = desc => desc.AsSwagger(
    with => with.Operation(
        op => op.OperationId("HeadOfProduct")
                .Tags(new List<string>() { "Products", "Products2" })//同时属于两个分组
                .Summary("Something is deprecated")
                .Description("This returns only http header")
                .IsDeprecated()//过时的,相当于常用的Obsolete,但是还可以用
                .Response(r => r.Description("Nothing will return but http headers"))                
    ));

作用如下:

起名 15

尽管如此已经标记为过时了,不过精神这些措施如故存在,所以也是能符合规律调用的。

壹 、大家新建一个Home视图页 那些视图页的效能就是 左右分栏 并添加权限验证

 起名 16起名 17

 

安然认证难题

Swagger帮助3种安全注解折格局:APIKEY、Basic、OAuth2.0,同样的Nancy.Swagger也协理,不过有点坑便是了。

选用的话有多个步骤(这里用最简易的APIKEY演示):

Step 1: 引用定义,在Bootstrapper中添加认证相关的内容

protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
    SwaggerMetadataProvider.SetInfo("Nancy Swagger Example", "v1.0", "Some open api", new Contact()
    {
        EmailAddress = "catcher_hwq@outlook.com",
        Name = "Catcher Wong",
        Url = "http://www.cnblogs.com/catcher1994",
    }, "http://www.cnblogs.com/catcher1994");

    var securitySchemeBuilder = new ApiKeySecuritySchemeBuilder();
    securitySchemeBuilder.Description("Authentication with apikey");
    securitySchemeBuilder.IsInQuery();
    securitySchemeBuilder.Name("Item1");           
    SwaggerMetadataProvider.AddSecuritySchemeBuilder(securitySchemeBuilder, "Item1");

    base.ApplicationStartup(container, pipelines);
}

Step 2 : 在MetadataModule中添加描述

Describe["Head"] = description => description.AsSwagger(
    with => with.Operation(
        op => op.OperationId("Head")
            .Tag("Head method")    
            .SecurityRequirement(SecuritySchemes.ApiKey)
            .Summary("an example head method")
            .Response(r => r.Description("OK"))));

当然,近期是未曾主意符合规律运行的!此时运维效果如下:

起名 18

单独打开/api-docs这些途径时提示如下错误:

起名 19

那个十有八九是Nancy.Swagger的平安认证留存bug的,那一个项目并未丰盛多的单元测试或者也是引致难题的一有个别原因。

察觉的第2bug是在MetadataModule中应用SecurityRequirement(SecuritySchemes.ApiKey)时一贯在报错,报错内容如下:

Nancy.RequestExecutionException: Oh noes! —<
System.InvalidCastException: Unable to cast object of type
‘Swagger.ObjectModel.SecuritySchemes’ to type ‘System.String’.
at
Swagger.ObjectModel.SwaggerModel.SwaggerSerializerStrategy.ToObject(IDictionary
source)

于是调节和测试源码,发未来Swagger.ObjectModel项目下的ToObject主意有标题

private static dynamic ToObject(IDictionary source)
{
    var expando = new ExpandoObject();
    var expandoCollection = (ICollection<KeyValuePair<string, object>>)expando;

    foreach (string key in source.Keys)
    {
        expandoCollection.Add(new KeyValuePair<string, object>(key, source[key]));
    }

    return expando;
}

从地点的失误内容也能知晓的看看,SecuritySchemes不可能转成string的,个中SecuritySchemes是三个枚举类型。

为了能符合规律运转,肯定要修改验证一下!!于是修改成如下 :

private static dynamic ToObject(IDictionary source)
{
    var expando = new ExpandoObject();
    var expandoCollection = (ICollection<KeyValuePair<string, object>>)expando;
    //用了var,在使用的时候强制ToString一下将其转成string
    foreach (var key in source.Keys)
    {
        expandoCollection.Add(new KeyValuePair<string, object>(key.ToString(), source[key]));
    }

    return expando;
}

由于在Mac上不可能打开那一个种类,所以地方的修改是切换回windows完结的。

拓展下边包车型地铁改动后,项目是早已能平常运作了!不过却少了二个很要紧的东西!

起名 20

在那几个艺术里面加了APIKEY验证的,不过小锁的记号却尚未出来!

从此相比较了Swagger的法定示例**http://petstore.swagger.io/**

起名 21

竟然有这么坑爹的工作!security是1个数组啊,不是3个对象啊~~

背后就修改了南希.Swagger里面包车型地铁比比皆是代码(瞎改的,只为了能健康运维),涉及了一点个类公事,就不一一表明了。

首先个难点已经提了PKoleos到那么些类型了,第②个难题还没找到相比较知足的方案,一时没提。

直接上最终的功力图,分别演示了,没有证明,验证成功和注明失利那三种情况!

起名 22

注:本文只演示了中间Nancy.Swagger的里边一种用法,而且还有一部分剧情是绝非涉嫌到的。还有三种其余用法有时间会拿出去和豪门分享。

贰 、咱们转到视图页 添加样式和布局  那里前端各人有个体的写法 笔者就不详细介绍了

咱俩先来做左栏
加载系统模块,我们抬高二个下拉菜单,让用户选用操作的体系

1 <select id="sel-system" >
2 <option value="选择系统"></option>
3 </select>

 

那里的下拉挑选,大家是应当出口到页面上的,所以
大家在 视图Home 下边获取那么些系统集合

 1         /// <summary>
 2         /// 权限管理 默认页面
 3         /// </summary>
 4         /// <returns></returns>
 5         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "View")]
 6         public ActionResult Home()
 7         {
 8             try
 9             {
10                 //获取用户可操作的系统列表
11                 ViewData["Systemlist"] = this.SystemManage.LoadSystemInfo(CurrentUser.System_Id);
12             }
13             catch(Exception e)
14             {
15                 WriteLog(Common.Enums.enumOperator.Select, "对模块权限按钮的管理加载导航页:", e);
16             }
17 
18             return View();
19         }

 

咱俩修改一下select 的 option 通过接受
后台的ViewData[“Systemlist”] 输出 下拉采用

1   <select id="sel-system">
2   @{
3       foreach (var item in ViewData["Systemlist"] as dynamic)
4       {
5         <option value="@item.ID">@item.NAME</option>
6        }
7     }
8   </select>

 

然后便是树形菜单了,以前用的是jquery.ztree.core-3.5
 前天换一换  用 jstree,大家看一下jstree json的格式

1 $('#using_json_2').jstree({ 'core' : {
2     'data' : [
3        { "id" : "ajson1", "parent" : "#", "text" : "Simple root node" },
4        { "id" : "ajson2", "parent" : "#", "text" : "Root node 2" },
5        { "id" : "ajson3", "parent" : "ajson2", "text" : "Child 1" },
6        { "id" : "ajson4", "parent" : "ajson2", "text" : "Child 2" },
7     ]
8 } });

 

理所当然,那是私下认可关闭的 展开呢
正是在性质里丰裕”state”: { “opened”: true
},笔者要关闭的,笔者就不加那一个了,那么遵照这几个格式,大家写二个主意,重临大家模块的json数据

本条点子 大家起名叫做 GetTree

 1         /// <summary>
 2         /// 获取模块树形菜单
 3         /// </summary>
 4         public ActionResult GetTree()
 5         {
 6             var json = new JsonHelper() { Msg = "Success", Status = "y" };
 7 
 8             //获取系统ID
 9             var sysId = Request.Form["sysId"];
10 
11             //判断系统ID是否传入
12             if (string.IsNullOrEmpty(sysId))
13             {
14                 json.Status = "n";
15                 json.Msg = "获取模块失败!";
16                 return Json(json);
17             }          
18             try
19             {
20                 //获取系统下的模块列表 按照 SHOWORDER字段 升序排列
21                 var query = this.ModuleManage.LoadAll(p =>  p.FK_BELONGSYSTEM == sysId).OrderBy(p => p.SHOWORDER).ToList();
22 
23                 //这里就是按照jsTree的格式 输出一下 模块信息
24                 var result = query.Select(m => new
25                 {
26                     id = m.ID,
27                     parent = m.PARENTID>0?m.PARENTID.ToString():"#",
28                     text = m.NAME,                    
29                     icon = m.LEVELS == 0 ? "fa fa-circle text-danger" : "fa fa-circle text-navy"
30                 }).ToList();
31 
32                 json.Data = result;
33             }
34             catch (Exception e)
35             {
36                 json.Status = "n";
37                 json.Msg = "服务器忙,请稍后再试!";
38                 WriteLog(Common.Enums.enumOperator.Select, "权限管理,获取模块树:", e);
39             }
40             return Json(json);
41         }

 

再回去大家Home视图页,用jstree呢
首先我们要引入它的css

起名 23

 

然后引入它的js

起名 24

 

咱俩在页面中新建三个DIV
来存放那些树形菜单

起名 25

 

写个精简的ajax获取数据
并且填充给地点拾叁分DIV

$.post("/permission/gettree", { sysId: $("#sel-system").val() }, function (res) {
                if (res.Status == "y") {
                    $("#ModuleTree").jstree({
                        "core": { "multiple": false, "data": res.Data }
                    }).on("changed.jstree", function (e, data) {
                        alert(data.instance.get_node(data.selected).text);
                    });
                }
                else {
                    dig.error(res.Msg);
                }
            });

 

因为大家以此是要挑选系统
然后列出系统下的树形菜单的,所以大家把这一个ajax方法
写到二个function方法里

 1  function ShowMoudle()
 2         {
 3             $("#ModuleTree").data('jstree', false).empty();
 4             $.post("/permission/gettree", { sysId: $("#sel-system").val() }, function (res) {
 5                 if (res.Status == "y") {
 6                     $("#ModuleTree").jstree({
 7                         "core": { "multiple": false, "data": res.Data }
 8                     }).on("changed.jstree", function (e, data) {
 9                         alert(data.instance.get_node(data.selected).text);
10                     });
11                 }
12                 else {
13                     dig.error(res.Msg);
14                 }
15             });
16         }

 

页面打开和系统下拉菜单select 更改的时候
加载这一个菜单,下边是全体的

起名 26

OK,是否出去了

起名 27

 

那接下去,大家要点击模块然后
操作模块的权杖,大家列出了树形菜单,上面做了一个方法正是 选中 菜单的时候
弹出 菜单的text

起名 28

笔者们要做的是,点击菜单的是后出示那么些模块的权力,所以,大家先新建一个权力列表页 

 

注意事项

在经过中还有三个须要10分注意的位置(本来那几个理应是在上一篇提及的):便是XXModule和XXMetadataModule相对应的职位关系。

南茜在那里限制的比较死,强制了上面三种处境:

Module所在的位置 MetadtaModule应该在的位置
./BlahModule ./BlahMetadataModule
./BlahModule ./Metadata/BlahMetadataModule
./Modules/BlahModule ../Metadata/BlahMetadataModule

那是文本分布所要注意的标题。

还有2个命名应该小心的标题:当大家对2个Module起名为ProductsModule时,它对应的MetadataModule一定假如ProductsMetadataModule。

而不可能是别的,有二次出于大意,忘记把s字母带上,花了很多光阴去找原因~~

上述三个难点的答案在Nancy.Metadata.Modules项目的DefaultMetadataModuleConventions类中。

叁 、权限管理

简言之总结

Nancy.Swagger给我们API文书档案化的征程上带来了重重的方便之处,除了安全评释这一块的标题不怎么坑,别的的终于比较正规,用起来也还算不难。

对于Swagger来说,通用性很好,只要提供的钦赐格式的多少就能很好的渲染出令人舒心的界面,大概那正是它这么流行的一个关键点吧。

上面是一张脑图不难的牢笼相关的始末 :

起名 29

本文已联手到Catcher写的南茜汇总博客:南希之大杂烩

① 、大家用Index那些视图 来突显模块列表页,大家给Index 添加权限验证 也是 查看

1         /// <summary>
2         /// 权限管理 权限列表
3         /// </summary>
4         /// <returns></returns>
5         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "View")]
6         public ActionResult Index()
7         {
8             return View();
9         }

 

② 、好的习惯,try  catch

 1      /// <summary>
 2         /// 权限管理 权限列表
 3         /// </summary>
 4         /// <returns></returns>
 5         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "View")]
 6         public ActionResult Index()
 7         {
 8             try
 9             {
10                 return View();
11             }
12             catch (Exception e)
13             {
14                 WriteLog(Common.Enums.enumOperator.Select, "对模块权限按钮的管理加载主页:", e);
15                 throw e.InnerException;
16             }
17         }

 

叁 、权限列表应该是某2个模块的权杖列表,由此,大家要选取三个模块ID的参数(怎么着传递的,待会再修改大家树形菜单的js,那里先不管)

 1 /// <summary>
 2         /// 权限管理 权限列表
 3         /// </summary>
 4         /// <returns></returns>
 5         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "View")]
 6         public ActionResult Index()
 7         {
 8             try
 9             {
10                 //获取模块ID
11                 var moduleId = Request.QueryString["moduleId"] ?? (Request["moduleId"] ?? "");
12 
13                 //如果模块ID不为空或NULL
14                 if(!string.IsNullOrEmpty(moduleId))
15                 {
16 
17                 }
18 
19                 return View();
20             }
21             catch (Exception e)
22             {
23                 WriteLog(Common.Enums.enumOperator.Select, "对模块权限按钮的管理加载主页:", e);
24                 throw e.InnerException;
25             }
26         }

 

④ 、要是ID不为空或NULL 大家 模块消息和模块的权力列表 传递给视图页

 1         /// <summary>
 2         /// 权限管理 权限列表
 3         /// </summary>
 4         /// <returns></returns>
 5         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "View")]
 6         public ActionResult Index()
 7         {
 8             try
 9             {
10                 //获取模块ID
11                 var moduleId = Request.QueryString["moduleId"] ?? (Request["moduleId"] ?? "");
12 
13                 //如果模块ID不为空或NULL
14                 if(!string.IsNullOrEmpty(moduleId))
15                 {
16                     //把模块ID转为Int
17                     int module_Id = int.Parse(moduleId);
18 
19                     //模块信息
20                     var module = this.ModuleManage.Get(p => p.ID == module_Id);
21 
22                     //绑定列表
23                     var query = this.PermissionManage.LoadAll(p => p.MODULEID == module.ID);
24 
25                     //关键字查询
26                     if (!string.IsNullOrEmpty(keywords))
27                     {
28                         query = query.Where(p => p.NAME.Contains(keywords));
29                     }
30                     //输出结果
31                     var result = query.OrderBy(p => p.SHOWORDER).ToList();
32 
33                     ViewBag.Search = base.keywords;
34 
35                     ViewBag.Module = module;
36 
37                     return View(result);
38                 }
39 
40                 return View();
41             }
42             catch (Exception e)
43             {
44                 WriteLog(Common.Enums.enumOperator.Select, "对模块权限按钮的管理加载主页:", e);
45                 throw e.InnerException;
46             }
47         }

 

⑤ 、大家在视图页 输出新闻 (注意一下,因为我们从未添加早先化权限的上马数据 所以 发轫化权限 按钮是不显得的)

起名 30起名 31

 1 @{
 2     Layout = "~/Views/Shared/_Layout.cshtml";
 3 }
 4 @model List<Domain.SYS_PERMISSION>
 5 <div class="wrapper wrapper-content  animated fadeInRight">
 6     <div class="row">
 7         <div class="col-sm-12">
 8             <div class="ibox float-e-margins">
 9                 <div class="ibox-title">
10                     @{
11                         if (ViewBag.Module != null)
12                         {
13                             Domain.SYS_MODULE module = ViewBag.Module as Domain.SYS_MODULE;
14                             if (module != null)
15                             {
16                                 <h5>@(module.NAME) - 权限</h5>
17                                 @Html.Hidden("moduleId", module.ID)
18                                 @Html.Hidden("moduleType", module.MODULETYPE)
19                             }
20 
21                             <div class="ibox-tools">
22                                 <a class="btn btn-primary btn-xs p310" id="reset" action="reset"><i class="im-plus"></i> 初始化权限</a>
23                                 <a class="btn btn-primary btn-xs p210" id="insert" action="add"><i class="fa fa-plus-circle fa-fw"></i> 创建新分类</a>
24                                 <a class="btn btn-warning btn-xs p210" id="modify" action="edit"><i class="fa fa-pencil fa-fw"></i> 编辑</a>
25                                 <a class="btn btn-danger btn-xs p210" id="delete" action="remove"><i class="fa fa-trash-o fa-fw"></i> 删除</a>
26                                 <a class="reload-link" style="color: #c4c4c4" href="javascript:dig.reload()" data-toggle="tooltip" data-placement="left" title="刷新">
27                                     <i class="fa fa-repeat fa-lg"></i>
28                                 </a>
29                             </div>
30                         }
31                         else
32                         {
33                             <h5>权限管理</h5>
34                         }
35                     }
36                 </div>
37                 <div class="ibox-content">
38                     @using (Ajax.BeginForm("Index", null, new AjaxOptions() { }, new { @id = "form1", @class = "form-horizontal", @method = "get" }))
39                     {
40                         <div class="row">
41                             <div class="col-sm-9">
42                             </div>
43                             <div class="col-sm-3">
44                                 <div class="input-group">
45                                     @Html.TextBox("Search", null, new { @class = "input-sm form-control", @placeholder = "请输入查询关键词" })
46                                     
47                                         <button type="submit" onclick="submit()" class="btn btn-sm btn-primary"> 搜索</button>
48                                     
49                                 </div>
50                             </div>
51                         </div>
52                     }
53                     <div class="row">
54                         <table id="dataTable" class="table table-striped table-bordered table-hover dataTables-example" style="text-align:center;">
55                             <thead>
56                                 <tr>
57                                     <th class="tn" style="width: 50px !important"><input name="checkall" class="icheck_box" type="checkbox" value=""></th>
58                                     <th>所属系统</th>
59                                     <th>权限动作</th>
60                                     <th>图标</th>
61                                     <th>顺序</th>
62                                 </tr>
63                             </thead>
64                             <tbody>
65                                 @{
66                                     if (Model != null)
67                                     {
68                                         @Html.Hidden("percount", Model.Count)
69                                         foreach (var item in Model)
70                                         {
71                                             <tr>
72                                                 <td class="tn"><input name="checkbox_name" class="icheck_box" type="checkbox" value="@item.ID"></td>
73                                                 <td><a href="javascript:modify('@item.ID')" listaction="detail">  @item.NAME</a></td>
74                                                 <td>@item.PERVALUE</td>
75                                                 <td style="color:#1ab394; "><i class="@item.ICON"></i></td>
76                                                 <td>@item.SHOWORDER</td>
77                                             </tr>
78                                         }
79                                     }
80                                 }
81                             </tbody>
82                         </table>
83                     </div>
84                 </div>
85             </div>
86         </div>
87     </div>
88 </div>
89 @section scripts{
90     <script type="text/javascript">     
91     </script>
92 }

View Code

 

⑥ 、大家再回去Home视图页,添加右栏,大家添加二个iframe

起名 32

iFrameHeight()是安装Iframe的可观,我们把这几个格局写在home视图里

1       function iFrameHeight() {
2             var ifm = document.getElementById("DeployBase");
3             var subWeb = document.frames ? document.frames["DeployBase"].document : ifm.contentDocument;
4             if (ifm != null && subWeb != null) {
5                 ifm.height = subWeb.body.scrollHeight + 30;
6             }
7         }

 

柒 、大家来修改一下树形菜单的 选中节点的主意 把模块的ID传递给Iframe

 起名 33

OK,到这里 大家Home应该是瓜熟蒂落了,下边就是 权限的拉长、修改、删除了

起名 34

起名 35

起名 36

 

四 、权限的 添加、修改、删除 (那几个跟上一篇模块基本是平等的 笔者就不详细表明了,只是微微判断的地点 笔者给大家看下)

一 、大家成立个视图 Detail

 1 /// <summary>
 2         /// 加载权限详情
 3         /// </summary>
 4         /// <param name="id"></param>
 5         /// <returns></returns>
 6         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "Detail")]
 7         public ActionResult Detail(int? id)
 8         {
 9             try
10             {
11                 var _entity = this.PermissionManage.Get(p => p.ID == id) ?? new Domain.SYS_PERMISSION();
12 
13                 //获取模块ID
14                 var moduleId = Request.QueryString["moduleId"];
15 
16                 if (!string.IsNullOrEmpty(moduleId))
17                 {
18                     int newmoduleid = int.Parse(moduleId);
19                     _entity.MODULEID = newmoduleid;
20                 }
21                 
22                 return View(_entity);
23             }
24             catch (Exception e)
25             {
26                 WriteLog(Common.Enums.enumOperator.Select, "对模块权限按钮的管理加载详情:", e);
27                 throw e.InnerException;
28             }
29         }

 

二 、那里呢,大家要获得权力操作的集聚,传递给视图页 供用户挑选(当然用户能够自定义权限,只是我们添加一局地常用的权柄 方便用户)

作者们要用到表SYS_CODE我们可能曾经有其一表了,不过从未多少
小编给大家有个别默许数据

起名 37起名 38

 1 USE [wkmvc_db]
 2 GO
 3 /****** Object:  Table [dbo].[SYS_CODE]    Script Date: 2016/6/1 17:37:41 ******/
 4 SET ANSI_NULLS ON
 5 GO
 6 SET QUOTED_IDENTIFIER ON
 7 GO
 8 CREATE TABLE [dbo].[SYS_CODE](
 9     [ID] [int] IDENTITY(1,1) NOT NULL,
10     [CODETYPE] [nvarchar](50) NULL,
11     [NAMETEXT] [nvarchar](200) NULL,
12     [CODEVALUE] [nvarchar](100) NULL,
13     [SHOWORDER] [int] NULL,
14     [ISCODE] [int] NULL,
15     [REMARK] [nvarchar](2000) NULL,
16     [CREATEDATE] [datetime] NULL,
17     [CREATEUSER] [nvarchar](36) NULL,
18     [UPDATEDATE] [datetime] NULL,
19     [UPDATEUSER] [nvarchar](36) NULL,
20     [PARENTID] [int] NULL,
21  CONSTRAINT [PK_SYS_CODE] PRIMARY KEY CLUSTERED 
22 (
23     [ID] ASC
24 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
25 ) ON [PRIMARY]
26 
27 GO
28 SET IDENTITY_INSERT [dbo].[SYS_CODE] ON 
29 
30 GO
31 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (1, N'ROLEVALUE', N'删除', N'Remove', 4, 1, N'删除所用到的权限值', CAST(0x0000A57500A49432 AS DateTime), N'管理员', CAST(0x0000A57500A49432 AS DateTime), N'管理员', 0)
32 GO
33 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (2, N'ROLEVALUE', N'导出', N'Export', 5, 1, N'导出所用到的权限值', CAST(0x0000A57500A49437 AS DateTime), N'管理员', CAST(0x0000A57500A49437 AS DateTime), N'管理员', 0)
34 GO
35 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (3, N'ROLEVALUE', N'导入', N'Import', 6, 1, N'导入所用到的权限值', CAST(0x0000A57500A49438 AS DateTime), N'管理员', CAST(0x0000A57500A49438 AS DateTime), N'管理员', 0)
36 GO
37 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (4, N'ROLEVALUE', N'审核', N'Audit', 7, 1, N'审核用到的权限值', CAST(0x0000A57500A49438 AS DateTime), N'管理员', CAST(0x0000A57500A49438 AS DateTime), N'管理员', 0)
38 GO
39 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (5, N'ROLEVALUE', N'回复', N'Reply', 8, 1, N'回复用到的权限值', CAST(0x0000A57500A49438 AS DateTime), N'管理员', CAST(0x0000A57500A49438 AS DateTime), N'管理员', 0)
40 GO
41 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (6, N'ROLEVALUE', N'分配', N'Allocation', 9, 1, N'分配用到的权限值', CAST(0x0000A57500A49438 AS DateTime), N'管理员', CAST(0x0000A57500A49438 AS DateTime), N'管理员', 0)
42 GO
43 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (7, N'ROLEVALUE', N'选择', N'Select', 10, 1, N'选择用到的权限值', CAST(0x0000A57500A49438 AS DateTime), N'管理员', CAST(0x0000A57500A49438 AS DateTime), N'管理员', 0)
44 GO
45 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (8, N'ROLEVALUE', N'上传', N'Upload', 11, 1, N'上传用到的权限值', CAST(0x0000A57500A49438 AS DateTime), N'管理员', CAST(0x0000A57500A49438 AS DateTime), N'管理员', 0)
46 GO
47 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (9, N'ROLEVALUE', N'下载', N'Download', 12, 1, N'下载用到的权限值', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
48 GO
49 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (10, N'ROLEVALUE', N'列表', N'List', 1, 1, N'列表用到的权限值', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
50 GO
51 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (14, N'ROLEVALUE', N'查看', N'View', 0, 1, N'查看所用到的权限值', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
52 GO
53 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (15, N'ROLEVALUE', N'详情', N'Detail', 1, 1, N'详情所用到的权限值', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
54 GO
55 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (16, N'ROLEVALUE', N'添加', N'Add', 2, 1, N'添加所用到的权限值', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
56 GO
57 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (17, N'ROLEVALUE', N'编辑', N'Edit', 3, 1, N'编辑用到的权限值', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
58 GO
59 INSERT [dbo].[SYS_CODE] ([ID], [CODETYPE], [NAMETEXT], [CODEVALUE], [SHOWORDER], [ISCODE], [REMARK], [CREATEDATE], [CREATEUSER], [UPDATEDATE], [UPDATEUSER], [PARENTID]) VALUES (18, N'ROLEVALUE', N'发布', N'Publish', 14, 1, N'发布所需权限', CAST(0x0000A57500A49439 AS DateTime), N'管理员', CAST(0x0000A57500A49439 AS DateTime), N'管理员', 0)
60 GO
61 
62 SET IDENTITY_INSERT [dbo].[SYS_CODE] OFF
63 GO
64 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'ID'
65 GO
66 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'代码类型' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'CODETYPE'
67 GO
68 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'代码显示文本' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'NAMETEXT'
69 GO
70 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'代码值' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'CODEVALUE'
71 GO
72 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'排序值' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'SHOWORDER'
73 GO
74 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否为编码(0否1是)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'ISCODE'
75 GO
76 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'备注' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'REMARK'
77 GO
78 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'CREATEDATE'
79 GO
80 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建者' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'CREATEUSER'
81 GO
82 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'修改时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'UPDATEDATE'
83 GO
84 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'修改者' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'UPDATEUSER'
85 GO
86 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'父级ID(使用时注意ISCODE为0)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SYS_CODE', @level2type=N'COLUMN',@level2name=N'PARENTID'
87 GO

View Code

 

③ 、我们在Service类库IService/SysManage上边添加3个接口 ICodeManage

起名 39起名 40

 1 using System.Collections.Generic;
 2 using System.Linq;
 3 
 4 namespace Service.IService
 5 {
 6     /// <summary>
 7     /// Service层代码配置接口
 8     /// add yuangang by 2015-05-22
 9     /// </summary>
10     public interface ICodeManage : IRepository<Domain.SYS_CODE>
11     {
12         /// <summary>
13         /// 根据编码类型获取编码集合
14         /// </summary>
15         /// <param name="codetype">编码类型</param>
16         /// <param name="codevalue">编码值</param>
17         List<Domain.SYS_CODE> GetCode(string codetype, params string[] codevalue);
18         /// <summary>
19         /// 通过字典查询字典指向的编码集合
20         /// </summary>
21         IQueryable<Domain.SYS_CODE> GetDicType();
22         /// <summary>
23         /// 根据字典ID与类型获取一条数据
24         /// </summary>
25         string GetCodeByID(int id, string codetype);
26         /// <summary>
27         /// 根据字典编码值与类型获取一条数据
28         /// </summary>
29         string GetCodeNameByCodeValue(string codeType, string codevalue);
30     }
31 }

View Code

 

肆 、大家在Service类库ServiceImp/SysManage下边它的兑现类 CodeManage

起名 41起名 42

 1 using Common;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Data.Entity;
 7 
 8 namespace Service.ServiceImp
 9 {
10     /// <summary>
11     /// Service层代码配置
12     /// add yuangang by 2015-05-22
13     /// </summary>
14     public class CodeManage : RepositoryBase<Domain.SYS_CODE>, IService.ICodeManage
15     {
16         /// <summary>
17         /// 根据编码类型获取编码集合
18         /// </summary>
19         public List<Domain.SYS_CODE> GetCode(string codetype, params string[] codevalue)
20         {
21             var predicate = PredicateBuilder.True<Domain.SYS_CODE>();
22             predicate = predicate.And(p => p.CODETYPE == codetype);
23             if (codevalue != null && codevalue.Length > 0)
24             {
25                 var str = codevalue.ToList();
26                 predicate = predicate.And(p => str.Contains(p.CODEVALUE));
27             }
28             return this.LoadAll(predicate).OrderBy(p => p.SHOWORDER).ToList();
29         }
30 
31         /// <summary>
32         /// 通过系统字典获取编码值
33         /// </summary>
34         public IQueryable<Domain.SYS_CODE> GetDicType()
35         {
36             Dictionary<string, string> code = Common.Enums.ClsDic.DicCodeType;
37             string dic = code.Aggregate(string.Empty, (current, item) => current + (item.Value + ",")).TrimEnd(',');
38             return this.LoadAll(p => dic.Contains(p.CODETYPE)).OrderBy(p => p.SHOWORDER);
39         }
40 
41         /// <summary>
42         /// 根据字典ID与类型获取一条数据
43         /// </summary>
44         public string GetCodeByID(int id, string codetype)
45         {
46             return (this.Get(p => p.ID == id) ?? new Domain.SYS_CODE()).NAMETEXT;
47         }
48 
49         /// <summary>
50         /// 根据字典编码值与类型获取一条数据
51         /// </summary>
52         public string GetCodeNameByCodeValue(string codeType, string codevalue)
53         {
54             if (string.IsNullOrEmpty(codevalue))
55                 return "";
56             var entity = this.Get(p => p.CODETYPE == codeType && p.CODEVALUE == codevalue);
57             if (entity == null) return "";
58             return entity.NAMETEXT;
59         }
60     }
61 }

View Code

小心:那里我们用到了1个 谓词表达式营造器

起名 43

自笔者把那些类
贴给我们,我们放到Common类库下边就可以

起名 44起名 45

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Linq.Expressions;
 5 using System.Text;
 6 
 7 namespace Common
 8 {
 9     /// <summary>
10     /// 谓词表达式构建器
11     /// add yuangang by 2015-09-08
12     /// </summary>
13     public static class PredicateBuilder
14     {
15         /// <summary>
16         /// 机关函数应用True时:单个AND有效,多个AND有效;单个OR无效,多个OR无效;混应时写在AND后的OR有效  
17         /// </summary>
18         /// <typeparam name="T"></typeparam>
19         /// <returns></returns>
20         public static Expression<Func<T, bool>> True<T>() { return f => true; }
21 
22         /// <summary>
23         /// 机关函数应用False时:单个AND无效,多个AND无效;单个OR有效,多个OR有效;混应时写在OR后面的AND有效  
24         /// </summary>
25         /// <typeparam name="T"></typeparam>
26         /// <returns></returns>
27         public static Expression<Func<T, bool>> False<T>() { return f => false; }
28 
29         public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
30                                                             Expression<Func<T, bool>> expr2)
31         {
32             return expr1.Compose(expr2, Expression.Or);
33         }
34 
35         public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
36                                                              Expression<Func<T, bool>> expr2)
37         {
38             return expr1.Compose(expr2, Expression.And);
39         }
40         public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
41         {
42             // build parameter map (from parameters of second to parameters of first)  
43             var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
44 
45             // replace parameters in the second lambda expression with parameters from the first  
46             var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
47 
48             // apply composition of lambda expression bodies to parameters from the first expression   
49             return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
50         }
51     }
52     public class ParameterRebinder : ExpressionVisitor
53     {
54         private readonly Dictionary<ParameterExpression, ParameterExpression> map;
55 
56         public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
57         {
58             this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
59         }
60 
61         public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
62         {
63             return new ParameterRebinder(map).Visit(exp);
64         }
65 
66         protected override Expression VisitParameter(ParameterExpression p)
67         {
68             ParameterExpression replacement;
69             if (map.TryGetValue(p, out replacement))
70             {
71                 p = replacement;
72             }
73             return base.VisitParameter(p);
74         }
75     }
76 }

View Code

 

五 、大家在瑟维斯类库下的Config/Service.xml添加一下布局

1  <!--预置编码管理-->
2   <object id="Service.Code" type="Service.ServiceImp.CodeManage,Service" singleton="false">
3   </object>

 

⑥ 、别忘了在WebPage/Config/Controllers.xml里注入一下

起名 46

 

柒 、大家在PermissionController 控制器里 声圣元下以此接口

起名 47

 

八 、我们修改一下 Detail 视图,获取一下 权限的预置编码

起名 48

 

玖 、修改 Detail视图页 展示权限音讯 成立 添加修改 表单

起名 49起名 50

  1 @{
  2     Layout = "~/Views/Shared/_Layout.cshtml";
  3 }
  4 @model Domain.SYS_PERMISSION
  5 <style type="text/css">
  6 .gray-bg {background-color: white;}
  7 .changeicon {float: right;margin-right: -52px;border: none;background-color: #18a689;color: #FFFFFF;height: 34px;margin-top: -7px;}
  8 .removeicon {background-color: #f8ac59;float: right;margin-right: -92px;border: none;color: #FFFFFF;height: 34px;margin-top: -7px;}
  9 </style>
 10 @using (Ajax.BeginForm("Save", null, new AjaxOptions()
 11                            {
 12                                HttpMethod = "Post",
 13                                OnBegin = "SubAjax.Loading",
 14                                OnComplete = "SubAjax.Complate",
 15                                OnFailure = "SubAjax.Failure",
 16                                OnSuccess = "SubAjax.Success"
 17                            },
 18                                new { @class = "form-horizontal dig-from", @role = "form" }))
 19 {
 20     @Html.HiddenFor(p => p.ID)
 21     @Html.HiddenFor(p => p.MODULEID)
 22     <div class="wrapper wrapper-content animated fadeInUp">
 23         <div class="row">
 24             <div class="ibox-detail-title">
 25                 <i class="fa fa-pencil-square-o"></i>添加/修改权限
 26             </div>
 27             <div class="ibox-content">
 28                 <div class="form-group">
 29                     <label class="col-sm-3 control-label">权限名称:</label>
 30                     <div class="col-sm-8">
 31                         @Html.TextBoxFor(p => p.NAME, new { @class = "form-control", @id = "modulename", @placeholder = "请输入权限名称", @datatype = "*", @nullmsg = "请输入权限名称!", @errormsg = "请输入权限名称!" })
 32                     </div>
 33                 </div>
 34                 <div class="hr-line-dashed"></div>
 35                 <div class="row">
 36                     <div class="col-sm-6 b-r">
 37                         <div class="form-group">
 38                             <label class="col-sm-3 control-label">权限值(英文):</label>
 39                             <div class="col-sm-8">
 40                                 <select id="PERVALUE" name="PERVALUE" class="form-control input-s-sm">
 41                                     <option value="">请选择</option>
 42                                     @{
 43                                         var per = ViewData["PresetValue"] as List<Domain.SYS_CODE>;
 44                                         if (per != null && per.Count > 0)
 45                                         {
 46                                             foreach (var item in per)
 47                                             {
 48                                                 <option value="@item.CODEVALUE" @(Model.PERVALUE == item.CODEVALUE ? "selected" : "")>@item.NAMETEXT</option>
 49                                             }
 50                                         }
 51                                     }
 52                                 </select>
 53                             </div>
 54                         </div>
 55                     </div>
 56                     <div class="col-sm-6">
 57                         <div class="form-group">
 58                             <div class="col-sm-12">
 59                                 @Html.TextBox("NEXTPERVALUE", "", new { @class = "form-control input-s-sm" })
 60                             </div>
 61                         </div>
 62                     </div>
 63                 </div>
 64                 <div class="hr-line-dashed"></div>
 65                 <div class="form-group">
 66                     <label class="col-sm-3 control-label">权限图标:</label>
 67                     <div class="col-sm-8">
 68                         
 69                             @Html.Hidden("ICON", Model.ICON)
 70                             <a class="btn btn-primary btn-xs"><i class="@Model.ICON"></i></a>
 71                             <button class="changeicon" type="button">
 72                                 选择
 73                             </button>
 74                             <button class="removeicon" type="button">
 75                                 移除
 76                             </button>
 77                         
 78                     </div>
 79                 </div>
 80                 <div class="hr-line-dashed"></div>
 81                 <div class="form-group">
 82                     <label class="col-sm-3 control-label">显示顺序:</label>
 83                     <div class="col-sm-8">
 84                         @Html.TextBoxFor(p => p.SHOWORDER, new { @class = "form-control", @placeholder = "请输入显示顺序", @datatype = "n1-5", @nullmsg = "请输入显示顺序!", @errormsg = "显示顺序只能是数字!" })
 85                     </div>
 86                 </div>
 87                 <div class="hr-line-dashed"></div>
 88                 <div class="text-center">
 89                     <button class="btn btn-primary btn-save" type="submit"><i class="fa fa-check"></i> 确定保存</button>
 90                     <button class="btn btn-warning" id="btn-dig-close" type="button"><i class="fa fa-reply-all"></i> 取消返回</button>
 91                 </div>
 92             </div>
 93         </div>
 94     </div>
 95 }
 96 @section scripts{
 97     <script type="text/javascript">
 98         $(function () {
 99             $('.form-horizontal').initValidform();
100             if ($('#PERVALUE').val() == '' && $('#ID').val() != '') {
101                 $('#NEXTPERVALUE').val('@Model.PERVALUE');
102             }
103         });
104         //移除图标
105         $('.removeicon').click(function () {
106             $('#icon').find('a>i').attr('class', '');
107             $('#ICON').val('');
108         });
109         //选择图标
110         $('.changeicon').click(function () {
111             var oldicon = $('#icon').find('a>i');
112             top.dialog({
113                 title: '选择图标',
114                 url: '/Sys/Module/ShowIcon',
115                 width: 700,
116                 height: 380,
117                 data: oldicon.attr('class'), // 给 iframe 的数据
118                 onclose: function () {
119                     this.returnValue && oldicon.attr('class', this.returnValue) && $('#ICON').val(this.returnValue);
120                 },
121                 oniframeload: function () {
122                 }
123             }).showModal();
124             return false;
125         });
126     </script>
127 }

View Code

 

10、保存权限(这几个跟模块管理也是同样的流程,我一向把代码贴给大家)

起名 51起名 52

 1 /// <summary>
 2         /// 保存权限
 3         /// </summary>
 4         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "Add,Edit")]
 5         public ActionResult Save(Domain.SYS_PERMISSION entity)
 6         {
 7             bool isEdit = false;
 8             JsonHelper json = new JsonHelper() { Msg = "保存权限成功", Status = "n" };
 9             try
10             {
11                 if (entity != null)
12                 {
13                     if (System.Text.Encoding.GetEncoding("gb2312").GetBytes(entity.NAME.Trim()).Length > 50)
14                     {
15                         json.Msg = "权限的名称长度不能超过50个字符";
16                         return Json(json);
17                     }
18                     entity.ICON = Request.Form["ICON"];
19                     var nextpervalue = Request.Form["NEXTPERVALUE"];
20                     if (!string.IsNullOrEmpty(nextpervalue))
21                     {
22                         if (!Regex.IsMatch(nextpervalue, @"^[A-Za-z0-9]{1,20}$"))
23                         {
24                             json.Msg = "权限值只能以英文数字组成,长度不能超过20个字符";
25                             return Json(json);
26                         }
27                         entity.PERVALUE = nextpervalue;
28                     }
29                     //添加
30                     if (entity.ID <= 0)
31                     {
32                         entity.CREATEDATE = DateTime.Now;
33                         entity.UPDATEDATE = DateTime.Now;
34                         entity.UPDATEUSER = this.CurrentUser.Name;
35                         entity.CREATEUSER = this.CurrentUser.Name;
36                     }
37                     else //编辑
38                     {
39                         entity.UPDATEUSER = this.CurrentUser.Name;
40                         entity.UPDATEDATE = DateTime.Now;
41                         isEdit = true;
42                     }
43                     //同一模块下权限不能重复
44                     if (!this.PermissionManage.IsExist(p => p.NAME.Equals(entity.NAME) && p.ID != entity.ID && p.MODULEID == entity.MODULEID))
45                     {
46                         if (PermissionManage.SaveOrUpdate(entity, isEdit))
47                         {
48                             json.Status = "y";
49                         }
50                         else
51                         {
52                             json.Msg = "保存失败";
53                         }
54                     }
55                     else
56                     {
57                         json.Msg = "权限" + entity.NAME + "同一模块下已存在,不能重复添加";
58                     }
59                 }
60                 else
61                 {
62                     json.Msg = "未找到要保存的权限记录";
63                 }
64                 if (isEdit)
65                 {
66                     WriteLog(Common.Enums.enumOperator.Edit, "修改权限,结果:" + json.Msg, Common.Enums.enumLog4net.INFO);
67                 }
68                 else
69                 {
70                     WriteLog(Common.Enums.enumOperator.Add, "添加权限,结果:" + json.Msg, Common.Enums.enumLog4net.INFO);
71                 }
72             }
73             catch (Exception e)
74             {
75                 json.Msg = "保存权限发生内部错误!";
76                 WriteLog(Common.Enums.enumOperator.None, "对模块权限按钮的管理保存权限:", e);
77             }
78             return Json(json);
79         }

View Code

 

1① 、删除权限 同上

起名 53起名 54

 /// <summary>
        /// 删除权限
        /// </summary>
        [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "Remove")]
        public ActionResult Delete(string idList)
        {
            var json = new JsonHelper() { Msg = "删除权限成功", Status = "n" };
            try
            {
                if (!string.IsNullOrEmpty(idList))
                {
                    var idList1 = idList.Trim(',').Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(p => int.Parse(p)).ToList();
                    //判断查找角色是否调用
                    if (!this.RolePermissionManage.IsExist(p => idList1.Any(e => e == p.PERMISSIONID)))
                    {
                        //判断查找用户是否调用
                        if (!this.UserPermissionManage.IsExist(p => idList1.Any(e => e == p.FK_PERMISSIONID)))
                        {
                            this.PermissionManage.Delete(p => idList1.Any(e => e == p.ID));
                            json.Status = "y";
                        }
                        else
                        {
                            json.Msg = "有用户正在使用该权限,不能删除!";
                        }
                    }
                    else
                    {
                        json.Msg = "有角色正在使用该权限,不能删除!";
                    }
                }
                else
                {
                    json.Msg = "未找到要删除的权限记录";
                }
                WriteLog(Common.Enums.enumOperator.Remove, "删除权限,结果:" + json.Msg, Common.Enums.enumLog4net.WARN);
            }
            catch (Exception e)
            {
                json.Msg = e.InnerException.Message;
                WriteLog(Common.Enums.enumOperator.Remove, "对模块权限按钮的管理删除权限:", e);
            }
            return Json(json);
        }

View Code

亟待留意的是,我们在剔除权限的时候,需求判定
角色是还是不是调用了权力、用户是或不是调用了权力,所以 大家要再声称多个接口

起名 55

小心注入:

起名 56

 

UserPermissionManage
那些有了,但是RolePermissionManage 大家一般没做,下面讲过了
添加CodeManage 接口实现类和配置,都以千篇一律的
小编把接口和兑现类贴给大家,我们尝试一下 自个儿加上

起名 57起名 58

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Service.IService
 7 {
 8     /// <summary>
 9     /// Service层角色授权关系接口
10     /// add yuangang by 2015-05-22
11     /// </summary>
12     public interface IRolePermissionManage : IRepository<Domain.SYS_ROLE_PERMISSION>
13     {
14         /// <summary>
15         /// 保存角色权限
16         /// </summary>
17         /// <param name="roleId">角色ID</param>
18         /// <param name="newper">权限字符串</param>
19         /// <param name="sysId">系统ID</param>
20         /// <returns></returns>
21         bool SetRolePermission(int roleId, string newper, string sysId);
22     }
23 }

View Code

起名 59起名 60

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Service.IService;
 6 
 7 namespace Service.ServiceImp
 8 {
 9     /// <summary>
10     /// Service层角色授权关系接口
11     /// add yuangang by 2015-05-22
12     /// </summary>
13     public class RolePermissionManage : RepositoryBase<Domain.SYS_ROLE_PERMISSION>, IService.IRolePermissionManage
14     {
15         IPermissionManage PermissionManage { get; set; }
16         /// <summary>
17         /// 保存角色权限
18         /// </summary>
19         public bool SetRolePermission(int roleId, string newper, string sysId)
20         {
21             try
22             {
23                 //1、获取当前系统的模块ID集合
24                 var permissionId = this.PermissionManage.GetPermissionIdBySysId(sysId).Cast<int>().ToList();
25                 //2、获取角色权限,是否存在,存在即删除,只删除当前选择的系统
26                 if (this.IsExist(p => p.ROLEID == roleId && permissionId.Any(e => e == p.PERMISSIONID)))
27                 {
28                     //3、删除角色权限
29                     this.Delete(p => p.ROLEID == roleId && permissionId.Any(e => e == p.PERMISSIONID));
30                 }
31                 //4、添加角色权限
32                 if (string.IsNullOrEmpty(newper)) return true;
33                 //Trim 保证数据安全
34                 var str = newper.Trim(',').Split(',');
35                 foreach (var per in str.Select(t => new Domain.SYS_ROLE_PERMISSION()
36                 {
37                     PERMISSIONID = int.Parse(t),
38                     ROLEID = roleId
39                 }))
40                 {
41                     this.dbSet.Add(per);
42                 }
43                 //5、Save
44                 return this.Context.SaveChanges() > 0;
45             }
46             catch (Exception e) { throw e.InnerException; }
47         }
48     }
49 }

View Code

 

OK,====,好像还有个初步化权限,在Index视图页
大家有个ajax 开端化权限,大家在PermissionController
控制器里新建个初步化权限的方法 验证权限是Reset

起名 61

 

 1       /// <summary>
 2         /// 初始化权限,默认增删改查详情
 3         /// <param name="id">模块ID</param>
 4         /// </summary>
 5         [UserAuthorizeAttribute(ModuleAlias = "Permission", OperaAction = "Reset")]
 6         public ActionResult Reset(string id)
 7         {
 8             var json = new JsonHelper() { Status = "n", Msg = "初始化完毕" };
 9             try
10             {
11                 //判断模块ID 是否符合规范
12                 if (string.IsNullOrEmpty(id) || !Regex.IsMatch(id, @"^\d+$"))
13                 {
14                     json.Msg = "模块参数错误";
15                     WriteLog(Common.Enums.enumOperator.Allocation, "初始化权限,结果:" + json.Msg, Common.Enums.enumLog4net.ERROR);
16                     return Json(json);
17                 }
18                 //将 ID 转为 Int
19                 int newid = int.Parse(id);
20 
21                 //判断权限里 模块是否有了权限
22                 if (this.PermissionManage.IsExist(p => p.MODULEID == newid))
23                 {
24                     json.Msg = "该模块已存在权限,无法初始化";
25                     WriteLog(Common.Enums.enumOperator.Allocation, "初始化权限,结果:" + json.Msg, Common.Enums.enumLog4net.ERROR);
26                     return Json(json);
27                 }
28                 //添加默认权限 
29                 var per = new string[] { "查看,View", "列表,List", "详情,Detail", "添加,Add", "修改,Edit", "删除,Remove" };
30                 var list = new List<Domain.SYS_PERMISSION>();
31                 foreach (var item in per)
32                 {
33                     list.Add(new Domain.SYS_PERMISSION()
34                     {
35                         CREATEDATE = DateTime.Now,
36                         CREATEUSER = this.CurrentUser.Name,
37                         NAME = item.Split(',')[0],
38                         PERVALUE = item.Split(',')[1],
39                         UPDATEDATE = DateTime.Now,
40                         UPDATEUSER = this.CurrentUser.Name,
41                         MODULEID = newid,
42                         SHOWORDER = 0
43                     });
44                 }
45                 //批量添加
46                 if (this.PermissionManage.SaveList(list) > 0)
47                 {
48                     json.Status = "y";
49                 }
50                 else
51                 {
52                     json.Msg = "初始化失败";
53                 }
54                 WriteLog(Common.Enums.enumOperator.Allocation, "初始化权限,结果:" + json.Msg, Common.Enums.enumLog4net.INFO);
55             }
56             catch (Exception e)
57             {
58                 json.Msg = e.InnerException.Message;
59                 WriteLog(Common.Enums.enumOperator.Allocation, "对模块权限按钮的管理初始化权限:", e);
60             }
61             return Json(json);
62         }

 

今后OK了,权限的军事管制大家就完了了~~~

 

原创文章转发请保护劳动成果 http://yuangang.cnblogs.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图