`
梁利锋
  • 浏览: 81868 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

导航、权限管理及 Linq 应用

阅读更多
  最近做一个广告系统,后台管理部分使用 ASP.NET,使用了 VS2008 + .Net 3.5,还是使用我写的 DbEntry 做数据库接口,页面部分大部分使用 ASP.NET Ajax 的 UpdatePanel 来进行更新,效果很不错,而且,速度上也感觉比普通的非 Ajax 页面快。

  而对于权限部分,使用页面级访问控制,读取 Web.Config 的方式,导航使用 html 直接放在母板页中的方式,后来觉得这样,每增加一个页面或对页面改名,就需要修改两个地方,不是一个很好的解决方案。

  以前,在做互联星空的一个项目时,曾经设计了使用 XML 做配置,导入 TreeView 做导航的方式,目前虽然不是使用 TreeView 做导航,应该也一样是适用的。不过,这一次,不想使用 XML,而是考虑直接在程序中使用 List 或 Directory 来表示这个数据结构。

  试着写了一下这个结构,发现,还是使用类似数据库的结构比较简单。于是定义 Category 和 Link 类,另外定义 Navigation 类,增加两个静态字段 Categories 和 Links:
public class Category
{
    private static int IdSeed = 1;

    public int Id { get; set; }
    public string Name { get; set; }

    public Category()
    {
        Id = IdSeed++;
    }
}

public class Link
{
    private static int IdSeed = 1;

    public int Id { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public int Permission { get; set; }
    public bool Hide { get; set; }
    public int Category_Id { get; set; }

    public Link()
    {
        Id = IdSeed++;
    }
}

public static class Navigation
{
    public static readonly List<Category> Categories;
    public static readonly List<Link> Links;
}

  然后,在静态构造函数中初始化数据:
static Navigation()
{
    Categories = new List<Category>()
    {
        new Category(){ Id = 1, Name = "设备管理" },
        new Category(){ Id = 2, Name = "内容管理" },
        new Category(){ Id = 3, Name = "计划" },
        new Category(){ Id = 4, Name = "系统" },
    };

    int FullPermission = (int)(SysUserRole.管理员 | SysUserRole.编辑人员 | SysUserRole.审核人员);

    Links = new List<Link>()
    {
        new Link(){ Url = "Default", Permission = FullPermission, Hide = true },
        // 设备管理
        new Link(){ Name = "新建设备", Url = "PlayerEdit", Permission = FullPermission, Category_Id = 1 },
        new Link(){ Name = "设备列表", Url = "PlayerList", Permission = FullPermission, Category_Id = 1 },
        new Link(){ Url = "PlayerManager", Permission = FullPermission, Hide = true, Category_Id = 1 },
        new Link(){ Category_Id = 1 },
        new Link(){ Name = "新建分组", Url = "PlayerGroupEdit", Permission = FullPermission, Category_Id = 1 },
        new Link(){ Name = "分组列表", Url = "PlayerGroupList", Permission = FullPermission, Category_Id = 1 },
        // 内容管理
        ......
        // 计划
        ......
        // 系统
        new Link(){ Name = "新建帐户", Url = "SysUserEdit", Permission = FullPermission, Category_Id = 4 },
        new Link(){ Name = "帐户列表", Url = "SysUserList", Permission = FullPermission, Category_Id = 4 },
        new Link(){ Category_Id = 4 },
        new Link(){ Name = "新建客户", Url = "CustomerEdit", Permission = FullPermission, Category_Id = 4 },
        new Link(){ Name = "客户列表", Url = "CustomerList", Permission = FullPermission, Category_Id = 4 },
    };
}

  其中,空的 Link 表示显示一个 hr 标签,用来分组,Url 是去掉“.aspx”之后的名字,Permission 用来对页面可访问性进行授权,这种方式,对于 int32 而言,可以提供 32 种权限,应该是足够了,当然,各种权限应该按 2 的幂的方式递增,如 1、2、4、8。这样,在判断是否有权限的时候,只要用“(Permission & p) == p”来判断就可以了。

  导航的 html 改在 Navigation 类中生成,然后填入母板页中的方式,使用 DbEntry 中的 HtmlBuilder 来生成 html 片段:
public static string BuildNavigator(int Permission)
{
    HtmlBuilder hb = HtmlBuilder.New.div.id("accmenu").enter();
    foreach (var c in Categories)
    {
        int count = 0;
        var b = HtmlBuilder.New.tab.div.enter();
        b.tab.tab.div.Class("acctitle").text(c.Name).end.enter();
        b.tab.tab.div.enter();
        var list = Links.Where(p => p.Category_Id == c.Id).ToList();
        foreach (var n in list)
        {
            if (string.IsNullOrEmpty(n.Url))
            {
                b.include("\t\t\t<hr />\r\n");
            }
            else
            {
                if (!n.Hide && (n.Permission & Permission) == Permission)
                {
                    count++;
                    b.include("\t\t\t<img src=\"images/h2.gif\" align=\"absmiddle\" /> ");
                    b.a(n.Url + ".aspx").text(n.Name).end.br.enter();
                }
            }
        }
        b.tab.tab.end.enter().tab.end.enter();
        if (count > 0)
        {
            hb.include(b);
        }
    }
    hb.end.enter();
    return hb.ToString();
}

  上面的代码,会生成类似以下的 html :
<div id="accmenu">
    <div>
        <div class="acctitle">设备管理</div>
        <div>
            <img src="images/h2.gif" align="absmiddle" /> <a href="PlayerEdit.aspx">新建设备</a><br />
            <img src="images/h2.gif" align="absmiddle" /> <a href="PlayerList.aspx">设备列表</a><br />
            <hr />
            <img src="images/h2.gif" align="absmiddle" /> <a href="PlayerGroupEdit.aspx">新建分组</a><br />
            <img src="images/h2.gif" align="absmiddle" /> <a href="PlayerGroupList.aspx">分组列表</a><br />
        </div>
    </div>
    <div>
        ......
    </div>
    <div>
        ......
    </div>
    <div>
        <div class="acctitle">系统</div>
        <div>
            <img src="images/h2.gif" align="absmiddle" /> <a href="SysUserEdit.aspx">新建帐户</a><br />
            <img src="images/h2.gif" align="absmiddle" /> <a href="SysUserList.aspx">帐户列表</a><br />
            <hr />
            <img src="images/h2.gif" align="absmiddle" /> <a href="CustomerEdit.aspx">新建客户</a><br />
            <img src="images/h2.gif" align="absmiddle" /> <a href="CustomerList.aspx">客户列表</a><br />
        </div>
    </div>
</div>

  而,它的显示,使用的是 jQuery 的插件 jQuery Accordion ,按照自己想要风格配置 css,然后在母板页中加入:
jQuery().ready(function(){
    var w = $('#accmenu').accordion({
        header: 'div.acctitle',
        animated: false
    });
    w.activate(CategoryIndex);
});

  之所以要关闭动画效果,是为了根据当前页所在分类,自动激活相应的面板,自动激活的过程如果有动画,显得很奇怪,不过,还没有找到这个 jQuery 插件相关设置初始面板的方法......

  Navigation 类提供取得指定 Url 权限的功能,使用基本的 Linq 语法:
public static int GetPermission(string Url)
{
    var item = Links.Where(p => p.Url == Url).ToList();
    if (item.Count > 0)
    {
        return item[0].Permission;
    }
    return 0;
}

  因为,在生成 html 的时候,考虑了如果按照相应的权限,一个分类下没有任何项目,则不显示这个分类,所以,取 Index 要复杂一些,要根据相应的权限进行分组,所以相应的 Linq 语句也复杂一些,使用了 group by:
public static int GetIndex(string Url, int Permission)
{
    int id = FindCategoryId(Url);
    var item = from p in Links where (p.Permission & Permission) == Permission && p.Category_Id != 0
               group p by p.Category_Id into g select new { Category_Id = g.Key };
    var i = item.ToList().FindIndex(p => p.Category_Id == id);
    return i < 0 ? 0 : i;
}

public static int FindCategoryId(string Url)
{
    var item = Links.Where(p => p.Url == Url).ToList();
    if (item.Count > 0)
    {
        return item[0].Category_Id;
    }
    return 0;
}

  虽然我现在使用的是内存里的数据,不过,因为格式是很标准的数据库格式,所以,要把这个配置项放入数据库表里,或者序列化成 XML,也都是非常方便的  —— 虽然我认为这个必要性不高。

  从实现来看,这个方法的速度应该不会很快,不过,因为数据量小,而且对于页面来说,这些在内存里做的手脚只能算小Case,所以没有明显感觉速度上有任何差异。

  不过,目前对于这个方案,还有一些不满意,比如,Hide 参数考虑改成和 Permission 相似,则可以控制每一项在不同权限下的显示,比单纯的全局 Hide 要灵活得多。再比如,目前没有判断是否会出现两条分割线等等。

  另外一种实现方案是,把数据的定义放在每一个页面里,这样的话,虽然设置分散到了每一个页面,但是却更符合实际情况,而且,页面 Url 也可以通过反射得到,删除页面或者页面改名都更简单,也许是更好的解决方案吧。

  其实,我感觉很好的是,这个程序的页面风格、css 以及一些图片什么的,都是我做的,而且我感觉还挺漂亮的  ,来个运行截图:
  • 描述: 运行截图
  • 大小: 175.9 KB
分享到:
评论
7 楼 梁利锋 2008-05-19  
PostSharp 很酷,而且效率比 Reflection 高,值得一试。
6 楼 梁利锋 2008-05-16  
哦,原来这样。
DynamicProxy 确实不错,通用性很好。
5 楼 oldrev 2008-05-16  
因为对于一些不考虑客户端的web程序来说,似乎没必要自己调用自己的 WCF web 服务,不过现在我用 DynamicProxy 做了一个等价的拦截器解决了这个问题。
4 楼 梁利锋 2008-05-15  
@oldrev
为什么感觉效率很低呢?

就我自己的开发经验,感觉效率低,和真的效率低是两回事。

大部分时候,业务逻辑本身和数据库访问才是瓶颈,这时,权限系统效率的高低对于用户体验来说,没有实质性影响。
3 楼 oldrev 2008-05-14  
最近做了一个勉强算通用的权限系统,用 Attribute 给每一个 WCF 的 IService 方法分配一个 GUID,然后用拦截消息头检查自定义的 SessionId,总感觉效率很低
2 楼 梁利锋 2008-04-27  
@oldrev
谢谢 
1 楼 oldrev 2008-04-27  
很少见这么出色的 Web 系统界面!

相关推荐

    C#开发的仓储管理系统

    C#,全称C Sharp,是一种面向对象的、类型安全的编程语言,由微软公司推出,广泛应用于Windows平台上的应用程序开发,尤其在企业级应用中表现出色。结合.NET框架,C#提供了强大的数据库连接能力,这使得它成为开发...

    ASP.NET数据库项目案例导航

    这个"ASP.NET数据库项目案例导航"的压缩包显然包含了多个示例项目,旨在帮助学习者理解和应用ASP.NET与数据库交互的技术。让我们深入探讨一下其中可能包含的知识点。 首先,基础的ASP.NET Web Forms或MVC架构:这两...

    网站后台管理程序模版

    1. **用户管理**:用于注册、登录、权限分配、角色管理等功能,确保只有授权用户能访问后台系统。 2. **内容管理**:涵盖文章发布、分类管理、图片上传等,帮助管理员更新网站内容。 3. **数据统计**:提供各种图表...

    基于ASP.net的企业网站后台管理系统源码.zip

    3. **状态管理**:ASP.NET提供了多种状态管理机制,如视图状态、控制状态、隐藏字段、Session和Cookie,以保持用户在网页间导航时的数据。 4. **数据绑定**:ASP.NET的数据绑定机制使UI与数据源的连接变得简单,...

    ASP.NET人事管理系统源码

    可能还利用了LINQ(Language Integrated Query)来简化数据库查询,并通过ASP.NET Identity进行用户管理和权限控制。 总之,ASP.NET人事管理系统源码是一个综合性的应用,涉及到数据库设计、前端交互、后端处理和...

    visual C# 2005 数据库项目案例导航2

    9. **安全性与权限管理**:理解如何为数据库用户分配合适的权限,以及如何在代码中安全地存储和使用数据库凭据。 10. **性能优化**:包括但不限于使用存储过程、批处理操作、预编译SQL命令、数据缓存等方法提高...

    ASP.NET/c# Sql Server 学生学籍管理系统

    在实际的项目中,学籍管理系统可能还包括用户认证和授权功能,使用ASP.NET的Forms Authentication和Role Management进行用户身份验证和权限划分,确保只有授权的用户才能访问特定的功能。此外,系统可能还涉及到错误...

    Visual C#数据库项目案例导航(代码)

    书中的案例可能涉及各种应用场景,如员工管理系统、电子商务平台、库存管理等,涵盖从简单的CRUD操作到复杂的业务逻辑处理。在实践中不断探索和学习,能帮助读者快速成长为一名熟练的C#数据库开发者。

    企业管理软件平面广告客户资源标准管理系统.doc

    【企业管理软件平面广告客户资源标准管理系统】是一款专为企业设计的管理工具,旨在优化广告客户资源的管理和提升工作效率。系统采用B/S(Browser/Server)架构,完全基于Web,支持网络协同工作,允许用户在任何有...

    asp.net+管理系统经典案例

    这个案例可能涵盖了登录注册、权限管理、数据展示、表单处理、报表生成等多个功能模块,这些都是企业级应用中常见的需求。 通过学习这个案例,你可以了解到如何: - 设计和实现用户身份验证和授权系统。 - 使用...

    Asp.net企业项目资料管理系统_xmmangement.zip

    这种权限控制增强了系统的安全性,防止了未授权的访问和操作。 系统可能还包含了文件上传和下载功能,Asp.net的HttpPostedFileBase类可以处理文件上传,将文件保存在服务器的特定目录下。同时,使用HttpResponse的...

    C#写的一个针对开发团队内部使用的资源导航系统源码.zip

    这是一个基于C#编程语言开发的资源导航系统源代码,专为开发团队内部使用而设计。这个系统的主要目标是提供一个高效、便捷的方式,帮助团队成员快速定位和利用各种开发资源,如API文档、代码示例、教程、工具库等。...

    用C#+XML实现动态导航菜单

    在IT行业中,动态导航菜单是Web应用和桌面应用中常见的一种设计模式,它可以根据用户权限、操作环境等因素自动生成和更新。本主题聚焦于如何利用C#编程语言和XML数据格式来实现这样的功能。C#作为.NET框架的主要开发...

    精通ASP.NET2.0网络应用系统开发随书光盘ch09

    4. ** Membership 和 Role Management**:ASP.NET 2.0提供了内置的用户身份验证和角色管理服务,便于实现安全的登录、注册和权限控制。 5. **站点导航**:可能涵盖了SiteMapProvider和TreeView、Menu等控件的使用,...

    软件开发的详细过程 图书管理系统

    - 用户和角色管理模块:管理用户信息及分配不同权限的角色。 - 书籍信息类别管理模块:分类管理书籍。 - 书籍信息管理模块:处理书籍的增删改查等操作。 - 书籍附件和图片管理模块:管理和维护书籍相关的附件和...

    Asp.net用户管理系统

    在Asp.net开发环境中,构建一个用户管理系统是常见的任务,涉及到用户的身份验证、授权、注册、登录、权限管理等多个方面。在这个系统中,"对树控件的操作"是一个关键的组成部分,它通常用于呈现层次化的数据结构,...

    网上导航系统B\S结构

    ASP.NET提供了丰富的功能和工具,包括页面生命周期管理、内置的安全机制、自动状态管理等,极大地简化了Web应用的开发过程。C#是ASP.NET的主要编程语言,它是一种面向对象的、类型安全的语言,具有现代编程语言的...

    亮剑ASP.NET项目开发案例导航 ppt

    《亮剑ASP.NET项目开发案例导航》PPT是针对ASP.NET技术在实际项目中的应用进行深入探讨和指导的资料。这份文档旨在帮助开发者理解和掌握ASP.NET的核心概念,并通过丰富的案例来提升开发技能。 首先,ASP.NET是微软...

    ProductManageSystem

    《产品管理系统——基于Bootstrap、Linq与Asp.net的实现》 在信息技术领域,开发一个高效、用户友好的产品管理系统是企业信息化建设的关键步骤之一。本文将深入探讨一个名为"ProductManageSystem"的项目,该项目...

    .NET项目 图书管理系统

    8. 报表与统计:系统可能还包括报表和统计功能,利用数据分析工具(如LINQ、EF Core的聚合函数等)生成图书借阅统计、热门图书排行等报告,帮助管理员了解图书馆运营状况。 9. 部署与维护:项目完成后,需要将其...

Global site tag (gtag.js) - Google Analytics