好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Web开发框架之权限管理系统

Web开发框架之权限管理系统

记得我在很早之前,开始介绍我的 Winform开发框架 和我的WCF开发框架之初,我曾经给出下面的视图,介绍我整理的一个框架体系,其中包含有WInform开发框架以及我的Web开发框架,由于前段时间一直忙于Winform开发框架的提炼以及优化,并统一整理了很多Winform开发框架以及WCF开发框架的随笔文章。随着我的Winform逐步完善,终于有时间来整理介绍我的Web开发框架的事宜了,下面先介绍一下我最新优化整理的Web开发框架之权限管理系统,其中这个权限管理系统可以说是集众多宠爱于一身了,除了一贯的和代码生成工具集成,可生成基础性的框架代码外,还整合Winform开发框架继承而来的多数据库支持,在界面层,也就是Web权限管理系统,整合了JQuery的Easy-UI界面组件,功能强大的zTree控件、KindEditor在线编辑控件、界面层获取数据及保存使用基于JQuery的json数据操作,实现数据局部刷新等等操作,其中提供两种不同的菜单布局操作,非常方便应用于其他业务系统的界面。

首先在介绍之前,我们来贴几个Web权限系统的图片进行感性的了解先。

1)简洁的界面布局效果。这种效果顶部横幅比较紧凑,左边有一些常用的按钮操作,适合于菜单功能不太多的小业务系统,如我的Web权限系统。

2)功能强大的界面企业业务系统布局。这种界面效果适合于功能比较众多,菜单展示进行分类管理等业务系统。这种框架顶部的菜单为一级菜单,单击一级菜单可以在左边展示二级菜单,这种效果可以不用一次性列出所有系统的功能,而是分层次进行功能展示。

顶部的Tab选项卡每次打开页面的时候,增加一个Tab页,页面可以双击进行关闭,也可以右键弹出菜单进行更多操作,如下图所示。

如果需要了解整个系统的效果,也可以下载《 Web权限系统操作视屏 》进行全面的了解。

在提炼优化这个Web权限框架的过程中,碰到了不少的问题,一一进行解决,现总结一部分进行进行介绍。

1)使用JSON数据构造zTree

使用zTree确实比easy-ui自带的Tree好很多,功能也强大很多,由于我的Web权限中,各个模块几乎都需要树控件来展示相关的数据,如功能、组织机构等等。在对比了我自己的传统Tree、Easy-UI的Tree控件以及zTree后,发现使用zTree还是可以提高不少的界面分数的。但是其自带的例子,以及网上的例子,多数是使用预先弄好的树形数据,而我需要动态使用ashx进行树形数据的获取及生成,这确实费了一些周折来进行调试。

首先要准备基于ashx处理程序生成的Tree数据,树的数据使用JSON格式。如功能定义的树形数据如下所示。

         ///   <summary> 
         ///   递归获取树形信息
          ///   </summary> 
         private   string  GetTreeJson( int  PID,  string  folderIcon,  string   leafIcon)
        {
              string  condition =  string .Format( "  PID={0}  "  , PID);
            List <FunctionInfo> nodeList = BLLFactory<Function> .Instance.Find(condition);
            StringBuilder content  =  new   StringBuilder();
              foreach  (FunctionInfo model  in   nodeList)
            {
                  int  ParentID = (model.PID == - 1  ?  0   : model.PID);
                  //  string tempMenu = string.Format("{{ id:{0}, pId:{1}, name:\"{2}\",icon:\"{3}\" }},", model.ID, ParentID, model.Name, imgsrc); //简单的作法 
                 string  subMenu =  this  .GetTreeJson(model.ID, folderIcon, leafIcon);
                  string  parentMenu =  string .Format( "  {{ \"id\":{0}, \"pId\":{1}, \"name\":\"{2}\"   "  , model.ID, ParentID, model.Name);
                  if  ( string  .IsNullOrEmpty(subMenu))
                {
                      if  (! string  .IsNullOrEmpty(leafIcon))
                    {
                        parentMenu  +=  string .Format( "  ,\"icon\":\"{0}\" }},  "  , leafIcon);
                    }
                      else  
                    {
                        parentMenu  +=  "  },  "  ;
                    }
                }
                  else  
                {
                      if  (! string  .IsNullOrEmpty(folderIcon))
                    {
                        parentMenu  +=  string .Format( "  ,\"icon\":\"{0}\" }},  "  , folderIcon);
                    }
                      else  
                    {
                        parentMenu  +=  "  },  "  ;
                    }
                }

                content.AppendLine(parentMenu.Trim());
                content.AppendLine(subMenu.Trim());
            }

              return   content.ToString().Trim();
        }  

然后就是页面的调用了,这里为了增强体验效果,使用了基于javascript的JQuery的异步操作进行数据处理,而不是基于aspx后台页面的处理,如下所示。

         //  重新加载树形结构(异步) 
         function reloadTree() {
            $(  "  #loading  "  ).show();
            $.getJSON(  "  http://www.cnblogs.com/AjaxHandler/FunctionJson.ashx?r=  "  + Math.random() +  "  &op=tree  "  , function (json) {
                $.fn.zTree.init($(  "  #treeDemo  "  ), setting, json);
                $.fn.zTree.getZTreeObj(  "  treeDemo  " ).expandAll( true  );

                  var  treeObj = $.fn.zTree.getZTreeObj( "  treeDemo  "  );
                  var  treeNodes =  treeObj.getNodes();
                  if  (treeNodes !=  null  ) {
                    loadData(treeNodes[  0  ].id);
                }
            });
            $(  "  #loading  " ).fadeOut( 500  );
        } 

这样处理的效果是页面只是局部刷新,体验很好。

2)基于JQuery的数据加载及保存操作

由于JQuery的方便性及良好体验性,我统一了数据的获取及保存操作。下面给出相关的处理代码供参考。

         //  加载制定的对象数据 
         function loadData(id) {
            $(  "  #loading  "  ).show();
            $.getJSON(  "  http://www.cnblogs.com/AjaxHandler/FunctionJson.ashx?r=  "  + Math.random() +  "  &op=findbyid&id=  "  +  id, function (json) {
                $(  "  #txtID  "  ).val(json.ID);
                $(  "  #txtName  "  ).val(json.Name);
                $(  "  #txtControlID  "  ).val(json.ControlID);
                $(  "  #txtPID  "  ).val(json.PID);
            });

            $(  '  #lbxRoles  '  ).empty();
            $.getJSON(  "  http://www.cnblogs.com/AjaxHandler/RoleJson.ashx?r=  "  + Math.random() +  "  &op=getrolesbyfunction&id=  "  +  id, function (json) {
                $.each(json, function (i, item) {
                    $(  '  #lbxRoles  ' ).append( '  <option value="  '  + item.ID +  '  ">  '  + item.Name +  '  </option>  '  );
                });
            });
            $(  "  #loading  " ).fadeOut( 500  );
        }

          //  保存对象数据 
         function saveData() {
            $.ajax({
                type:   '  POST  '  ,
                url:   '  http://www.cnblogs.com/AjaxHandler/FunctionJson.ashx?r=  '  + Math.random() +  '  &op=insert  '  ,
                async:   false  ,
                data: { ID: $(  "  #txtID  " ).val(), Name: $( "  #txtName  " ).val(), ControlID: $( "  #txtControlID  " ).val(), PID: $( "  #txtPID  "  ).val() },
                success: function (id) {
                    alert(  "  操作成功!   "  );
                    reloadTree();

                      if  (id !=  ""  )
                        loadData(id);
                },
                error: function (xhr, status, error) {
                    alert(  "  操作失败  " );  //  xhr.responseText 
                 }
            });
        } 

3)在数据操作等待的时候,页面中间显示Loading效果。

整个系统,在各种请求操作,我都统一了作法,在界面显示Loading的等待效果,任务结束后关闭,这种效果在费事的操作,用户体检会好一些,下面看看其效果以及实现代码。

增加下面javascript脚本

         //  对象居中的函数,调用例子:$("#loading").center(); 
        jQuery.fn.center =  function   () {
              this .css("position", "absolute" );
              this .css("top", Math.max(0, (($(window).height() -  this .outerHeight()) / 2) + 
                                                $(window).scrollTop())  + "px" );
              this .css("left", Math.max(0, (($(window).width() -  this .outerWidth()) / 2) + 
                                                $(window).scrollLeft())  + "px" );
              return   this  ;
        }

          //  初始化对象 
        $(document).ready( function   () {

            $( "#loading").center(); //  loading的图片显示居中 
        });

然后再页面Body后面增加一行代码即可(默认loading图片不显示的哦)。

     <  div   id  ="loading"   style  ="display: none;"  ><  img   alt  ="数据正在加载中..."   src  ="http://images.cnblogs.com/loading02.gif"   /></  div  > 

4)控件数据清空操作

由于添加和编辑公用界面控件元素,因此我们在要添加数据的时候,需要清空或者设置某些控件的值,但我们的控件可能比较多,一种好的方法是利用JQuery的选择器功能来进行有目的的控件清空操作。

如下面的例子所示。

         //  新增清空控件 
         function   addData() {
            $( "#txtPID").val($("#txtID" ).val());
            $( "input[type=text][id*='txt']").val("" );
            $( "textarea[id*='txt']" ).empty();
            $( "select[id*='lbx']" ).empty();
        } 

其中$("#txtPID").val($("#txtID").val());是把当前的用户作为添加数据的上级,其他的就是清空控件的数据了,不同的类型控件清空的步骤有些不同。

5)Ashx处理程序的安全性考虑

我们在系统中,多数都是调用ashx进行数据处理,虽然一般业务系统在VPN或者内网中运行,但是也要考虑用户没登陆的时候,不运行调用ashx程序,这样可以提高数据的安全性。

默认的ashx处理程序是没有Session的操作的,所以我们需要修改其继承接口(多增加 IReadOnlySessionState  的继承)

,然后才能调用Session来进行判断。

     ///   <summary> 
     ///   权限功能操作类
      ///   </summary> 
    [WebService(Namespace =  "  http://tempuri.org/  "  )]
    [WebServiceBinding(ConformsTo  =  WsiProfiles.BasicProfile1_1)]
      public   class   FunctionJson : IHttpHandler, IReadOnlySessionState 
    {        
          public   void   ProcessRequest(HttpContext context)
        {
              //  类对象要显式的实现接口 IReadOnlySessionState,才能访问Session数据 
             if  (context.Session[ "  Identity  " ] ==  null  )
            {
                  throw   new  ArgumentException( "  用户未登录!  "  );
            } 

6)Tab界面布局的兼容。

Web权限系统提供了两种常用的菜单布局进行管理,一般对于常用的业务系统肯定是没问题了。

另外一种效果是系统复杂的时候用的,可以定义一级菜单和关联的二级菜单。

对于后者,一级菜单打开的时候,可以关联打开一个新的页面,并且刷新二级菜单的关系。

         <!--  --------- 一级导航 ----------------  --> 
         <  ul   class  ="navigation"   style  ="display:block"  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('ListUser.aspx', '用户管理', 'default')"  > 权限管理 </  a  ></  li  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('Commonpage/MyJob.aspx', '事务中心开发中...', 'point', 'icon-organ')"  > 事务中心 </  a  ></  li  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('Commonpage/building.htm', '合同起草开发中...', '')"  > 合同起草 </  a  ></  li  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('Commonpage/building.htm', '合同管理开发中...', '')"  > 合同管理 </  a  ></  li  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('Commonpage/building.htm', '查询打印开发中...', '')"  > 查询打印 </  a  ></  li  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('Commonpage/building.htm', '知识管理开发中...', '')"  > 知识管理 </  a  ></  li  > 
             <  li  ><  a   href  ="#"   onclick  ="showSubMenu('Commonpage/building.htm', '系统管理开发中...', '')"  > 系统管理 </  a  ></  li  > 
         </  ul  > 

 好了,很多其他的特点,以后继续介绍,欢迎多多提出宝贵意见。

主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架 、WCF开发框架的研究及应用。
  转载请注明出处:
撰写人:伍华聪   http://www.iqidi.com  
    

 

标签:  Web开发框架

一步一步Asp.Net MVC系列_权限管理数据库与ViewModel篇

 

在上一篇中我们讲了大致怎么搭建一个项目,以及一个项目的基本构架,这一次,我们讲解基本的权限管理思路.

说道权限管理,相信大家都不太陌生,这个东西几乎什么系统都会涉及到,因此,抽出时间去思考,去研究复用的模块,架构,就是一个非常好的提升水平的方式,特别是对于我们这些学生来说,没有太多经验,更需要去研究这些东西来更多的掌握实战方面的技巧.数据库设计是一个几乎人人都要面对的一个话题,我就来讲,我的数据库设计.当然只是个人见解,博客园的很多人都设计的各种各样的权限,各种各样的思路,但是可能大多数设计的比较复杂,我只是从一个菜鸟的角度讲解,我能够理解的权限管理.

首先是数据库设计 :

在此期间,我们贴上powerdesinger设计图

大致就是7张表:

tbModule模块表

tbModulePermission模块权限表

tbPermission权限表

tbRole角色表

tbRolePermission角色权限表

tbUserRole用户角色表

tbUser用户表

首先要注意的就是命名:

可以看到,我的数据库命名风格是非常统一的,呵呵,这个可能是习惯,tb代表table,如果是视图我就在前面加上v,后面全部是Pascal风格的命名,字母大写的方式.

一个清晰的命名可以让我们很容易看清细节,起一个好名字非常重要.

这也告诉我们,我们平时注意细节,命名,代码规范统一,让我们节省大量的时间.

在博客园看到很多权限设计思路,

我觉得上面这个可能是比较清晰的,呵呵,参考了好多人的设计,

权限设计要设计那些呢?

首先,一个模块对应多种权限,增删改查,导入导出等等等等,这里权限在mvc里面可以控制到每一个请求,每一个ajax响应,在mvc里面有一个很好的对应关系,一个模块对应就是一个控制器,一个action就是一个权限(当然这种可能太细了,但是我们可以先这么看),这样我们就需要在tbModule和tbPermission中间加一个tbModulePermission表了,因为不同角色的同一模块的权限可能都是不一样的,所以这里要加入一个tbModulePermission表.

其次,角色的设计,角色拥有模块权限,每个用户对应多种角色,这个用户可能即是普通管理员,又是其他后台编辑,等等,权限当然是不一样的.

这样一个思路就很明显了,角色直接拥有各种模块的功能权限,而用户可以扮演各种角色.

至于字段的设计,我看了很多人的设计,很多细节的字段,比如IsDeleted,CreateUserID,CreateDate,ModifyUserID,ModifyDate,Description这些几乎大部分表都是需要的,多加一些表,更是让设计更灵活.

数据库的设计ID用GUID的习惯,我还没有养成,可能现在没遇到麻烦吧,也是没有真正的工作经验,呵呵,别人都说应该主键用GUID,呵呵!

我看到很多人直接设计Menu和Button来表示tbModule和tbPermission,其实感觉从命名来讲,页面任何一个ajax请求都可以算是一种功能权限,可能不是Button,如果用Permission表示可能更好一点,至于Menu,我认为用Module来命名可能更好,在tbModule里面有一个IsMenu字段来表示是否是菜单,里面有一个Controller字段,其实大致对应一个Controller控制器,每一个模块在mvc中以控制器的方式展示,我们在设计UI菜单的时候也可以通过反射的方式来获取Controller,对于菜单的设计更友好,不需要自己去配置URL,更自由.当然,在Permission表里面有PermissionAction和PermissionController字段表示,每一个动作请求和对应的控制器.

对于菜单的添加我们可以做到非常轻松,点点点就能够配置好,以前需要在数据库输入的一些预定义的数据!

数据设计好了,这种数据库可能我感觉比较清晰.呵呵!

接下来,我们继续谈关于设计的问题,上次基本上已经讲完关于数据访问层的设计,这次讲解,关于ViewModel的设计和公共类库的设计,

ViewModel呵呵,我用它来干什么,我用它来做UI层和业务逻辑层交互的实体对象.

可能大家觉得EF已经帮我们设计了数据库的实体对象,为什么还要另外一个单独的层来定义交互的实体对象?

我把这个ViewModel就是和界面交互的实体对象,在EF基本上是根据数据库直接生成的实体,所以命名字段都是跟数据库紧密结合在一起的,往往我们给UI层展示的时候,要做大量的处理,而UI交互,经常性我们用的后台框架都要求提供指定格式的json数据,我们以前甚至这么干过,从数据访问层直接select DeptID as id,name as title from deptment……………这种代码简直太坑爹了,而几乎数据库的东西和界面都关联到一起了,如果我们修改个字段,界面改点东西,两头都要动,所以,这种模式太痛苦了.

因此,我专门独立了一层,用来做UI和业务逻辑层的交互使用,这样ViewModel与UI更友好,用例子说说吧!

数据库的Permission在界面中大量显示为Button,我们就可以直接定义一个ViewModelButton类,来做UI和业务逻辑的交互,

如果对于普通字段的添加,我相信在这个代码中,你的改动非常少,几乎只是EF模型重新生成,ViewModel,和html界面传参的修改,我们的目标是,让修改更简单,业务的变动,我们仍然能够清晰的把握细节.

    1:    /*  作者:       tianzh 
    2:    *  创建时间:   2012/7/26 15:52:19 
    3:    * 
    4:    */ 
    5:    using  System;
    6:    using  System.Collections.Generic;
    7:    using  System.Linq;
    8:    using  System.Text;
    9:    using  System.Web;
   10:    using  TZHSWEET.Entity;
   11:    
   12:    namespace  TZHSWEET.ViewModel
   13:   {
   14:        public   class  ViewModelButton
   15:       {
   16:            #region  - 属性 -
   17:    
   18:            public   int  ID { get; set; }
   19:    
   20:            public   string  Action { get; set; }
   21:    
   22:            public   string  Name { get; set; }
   23:    
   24:            public   bool  IsVisible { get; set; }
   25:    
   26:            public   string  Script { get; set; }
   27:    
   28:            public   string  Icon { get; set; }
   29:    
   30:            public   string  Controller { get; set; }
   31:    
   32:            public   string  Description { get; set; }
   33:    
   34:            #endregion 
   35:    
   36:            #region  - 构造函数 -
   37:    
   38:            public  ViewModelButton()
   39:           {
   40:    
   41:           }
   42:    
   43:            public  ViewModelButton(HttpContextBase context)
   44:           {
   45:               ID = Convert.ToInt32(context.Request[ "ID" ]);
   46:               Action = context.Request[ "Action" ];
   47:               Name = context.Request[ "Name" ];
   48:               IsVisible = context.Request[ "IsVisible" ] ==  "1" ;
   49:               Script = context.Request[ "Script" ];
   50:               Icon = context.Request[ "Icon" ];
   51:                this .Controller = context.Request[ "Controller" ];
   52:    
   53:    
   54:           }
   55:    
   56:            #endregion 
   57:    
   58:            #region  - 方法 -
   59:            #region  ToEntity
   60:            public   static  tbPermission ToEntity(ViewModelButton permission)
   61:           {
   62:               tbPermission item =  new  tbPermission();
   63:               item.PermissionID = permission.ID;
   64:               item.PermissionName = permission.Name;
   65:               item.PermissionAction = permission.Action;
   66:               item.Script = permission.Script;
   67:               item.Icon = permission.Icon;
   68:               item.IsVisible = permission.IsVisible;
   69:               item.PermissionController = permission.Controller;
   70:               item.Description = permission.Description;
   71:                return  item;
   72:           }
   73:    
   74:            #endregion 
   75:            #region  ToViewModel
   76:            /// <summary> 
   77:            /// 转化为ViewModel 
   78:            /// </summary> 
   79:            /// <param name="permission"></param> 
   80:            /// <returns></returns> 
   81:            public   static  ViewModelButton ToViewModel(tbPermission permission)
   82:           {
   83:               ViewModelButton item =  new  ViewModelButton();
   84:               item.ID = permission.PermissionID;
   85:               item.Name = permission.PermissionName;
   86:               item.Action = permission.PermissionAction;
   87:               item.IsVisible = permission.IsVisible.Value;
   88:               item.Icon = permission.Icon;
   89:               item.Script = permission.Script;
   90:               item.Controller = permission.PermissionController;
   91:               item.Description = permission.Description;
   92:                return  item;
   93:           }
   94:    
   95:            /// <summary> 
   96:            /// 转化为List集合 
   97:            /// </summary> 
   98:            /// <param name="list"></param> 
   99:            /// <returns></returns> 
  100:            public   static  IEnumerable<ViewModelButton> ToListViewModel(IEnumerable<tbPermission> list)
  101:           {
  102:               var listModel =  new  List<ViewModelButton>();
  103:                foreach  (tbPermission item  in  list)
  104:               {
  105:                   listModel.Add(ViewModelButton.ToViewModel(item));
  106:               }
  107:                return  listModel;
  108:           } 
  109:            #endregion 
  110:    
  111:            #endregion 
  112:    
  113:    
  114:       }
  115:   }

一般情况下,我们只需要定义实体,和一个构造函数,这个构造函数,大家可能觉得为什么要传递HttpContext?

原因就是,封装Controller中的请求,把Controller中表单的数据请求单独用ViewModel处理,看看关于Controller的一个函数处理

我们把关于请求的数据从Controller中分离处理啊,Controller就相当简洁了,很清晰的看到具体的思路,而我们的业务逻辑层,就可以相当简洁的调用

而这个T是什么呢?T就是tbPermission实体这个东西了,是不是发现页面非常清晰,简洁?

而我们经常通用的几种UI格式,LigerUI Grid格式请求,Select格式请求,GridTree格式请求,Tree格式请求,都是ViewModel中的封装,

GridRequest请求的ViewModel:

    1:     /*  作者:       tianzh 
    2:     *  创建时间:   2012/7/19 18:16:08 
    3:     * 
    4:     */ 
    5:     /*  作者:       tianzh 
    6:     *  创建时间:   2012/7/16 15:31:37 
    7:     * 
    8:     */ 
    9:    
   10:    using  System;
   11:    using  System.Collections.Generic;
   12:    using  System.Linq;
   13:    using  System.Text;
   14:    using  System.Web;
   15:    namespace  TZHSWEET.ViewModel
   16:   {
   17:        public   class  LigerUIGridRequest
   18:       {
   19:    
   20:            private   string  sortOrder;
   21:    
   22:            private   int  pageSize;
   23:            /// <summary> 
   24:            /// 字段查看视图(暂时没做到) 
   25:            /// </summary> 
   26:            public   string  View
   27:           {
   28:               get;
   29:               set;
   30:           }
   31:            /// <summary> 
   32:            /// 排序字段名称 
   33:            /// </summary> 
   34:            public   string  SortName { get; set; }
   35:            /// <summary> 
   36:            /// 排序规则 
   37:            /// </summary> 
   38:            public   string  SortOrder
   39:           {
   40:               get
   41:               {
   42:                    if  ( this .sortOrder ==  "desc" )
   43:                        return   this .sortOrder;
   44:                    else 
   45:                        return   "asc" ;
   46:               }
   47:    
   48:               set
   49:               {
   50:                    this .sortOrder =  value ;
   51:               }
   52:           }
   53:            private   int  pageNumber;
   54:            /// <summary> 
   55:            /// 页号 
   56:            /// </summary> 
   57:            public   int  PageNumber
   58:           {
   59:               get
   60:               {
   61:                    if  ( this .pageNumber <= 0)
   62:                        return  1;
   63:                    else 
   64:                        return  pageNumber;
   65:               }
   66:               set
   67:               {
   68:                    if  ( value  <= 0)
   69:                       pageNumber = 1;
   70:                    else 
   71:                       pageNumber =  value ;
   72:               }
   73:           }
   74:            /// <summary> 
   75:            /// 每页的多少条数据 
   76:            /// </summary> 
   77:            public   int  PageSize 
   78:           {
   79:               get
   80:               {
   81:                    return   this .pageSize;
   82:               }
   83:               set
   84:               { 
   85:                   this .pageSize= ( value ==0?10: value );
   86:               }
   87:           }
   88:            /// <summary> 
   89:            /// 查询条件 
   90:            /// </summary> 
   91:            public   string  Where { get; set; }
   92:            /// <summary> 
   93:            /// 初始化读取信息 
   94:            /// </summary> 
   95:            /// <param name="context"></param> 
   96:            public  LigerUIGridRequest(HttpContextBase context)
   97:           {
   98:                this .View = context.Request[ "view" ];
   99:                this .SortName= context.Request[ "sortname" ];
  100:               this .SortOrder = context.Request[ "sortorder" ]== "desc" ? "desc" : "asc" ;
  101:               this .PageNumber =Convert.ToInt32(context.Request[ "page" ]);
  102:               this .PageSize =Convert.ToInt32(context.Request[ "pagesize" ]);
  103:                this .Where = context.Request[ "where" ];
  104:    
  105:           }
  106:       }
  107:   }

在这里我们可以做数据的校验工作,这样我们的控制器就非常非常的简洁了,

在业务逻辑层,我们可以通过Request的ViewModel模型,进行数据处理,

可以看到我们仅仅通过数据的封装就让我们的UI和业务逻辑更简洁,更丰富,

当然这个业务逻辑层写的很有问题..............就是业务逻辑层竟然直接返回json格式,这个大大的不好,因为我们的业务逻辑层尽可能的跟数据的展示格式没关系,应该直接返回数据,集合就直接返回IEnumerable<T>接口,而数据如何展示应该在控制器中控制.

一个好一点的方法设计就是这样子的,

可以看到我们的工作大部分就是让不同的类减压,尽量更简单,单一指责,如果一个类的职责过多就更难维护,特别是控制器,很容易出现大量的代码,

就像我们的这个

让代码更精简,这样我们才能更清晰,本来我们返回的Grid数据需要json化,我写了一个扩展方法,返回json,而且格式针对UI更友好,配合前台的封装的ajax,让消息的提示更友好,

前台利用LigerUI中的封装,

总结:可以看到我们每一部细节的改进,都能让我们代码更简洁,而且让我们的思路更清晰,清晰,才是我们的追求,清晰的代码是我们的追求!

 

注意:项目心得分享请加群,请加群:190678518(已满) 190678030(未满) mvc学习系列,等我写完权限管理,上传源码到网盘,呵呵! 一直在努力,从未曾放弃,努力学习中..... 欢迎一起学习.net!

分类:  .net ,  asp.net MVC ,  JQuery ,  Entity FrameWork实战 ,  权限管理设计

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Web开发框架之权限管理系统的详细内容...

  阅读:150次