Web层的搭建

前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码。之前的六篇完成了领域层、应用层、以及基础结构层的部分代码,这篇打算搭建下UI层的代码。

DDD领域驱动设计初探系列文章:

一、UI层介绍

在DDD里面,UI层的设计也分为BS和CS,本篇还是以Web为例来说明。我们的Web采用的是MVC+bootstrap的架构。Table组件使用的是bootstrap table,之所以用它是因为它的API比较全,并且博主觉得它的风格适用于各种类型的设备,无论是PC端还是手机端都都能很好的兼容各种浏览器。

这里还是贴出bootstrap API的相关地址。

Bootstrap中文网:http://www.bootcss.com/

Bootstrap Table Demo:http://issues.wenzhixin.net.cn/bootstrap-table/index.html

Bootstrap Table API:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/

Bootstrap Table源码:https://github.com/wenzhixin/bootstrap-table

Bootstrap DataPicker:http://www.bootcss.com/p/bootstrap-datetimepicker/

Bootstrap离线API

二、代码示例

上篇完成了WCF的设计代码,但是具体的业务逻辑的代码还没有,我们先来实现具体业务的CURD代码。

1、WCF代码

1.1 WCF服务业务接口代码

  1. /// <summary>
  2. /// 权限管理模块接口契约
  3. /// </summary>
  4. [ServiceContract]
  5. [ServiceInterface]
  6. public interface IPowerManageWCFService
  7. {
  8.  
  9. #region 用户管理
  10. [OperationContract]
  11. List<DTO_TB_USERS> GetUsers(ExpressionNode expressionNode);
  12.  
  13. [OperationContract]
  14. DTO_TB_USERS AddUser(DTO_TB_USERS oUser);
  15.  
  16. [OperationContract]
  17. bool DeleteUser(DTO_TB_USERS oUser);
  18.  
  19. [OperationContract]
  20. bool DeleteUserByLamada(ExpressionNode expressionNode);
  21.  
  22. [OperationContract]
  23. bool UpdateUser(DTO_TB_USERS oUser);
  24. #endregion
  25.  
  26. #region 部门管理
  27. [OperationContract]
  28. List<DTO_TB_DEPARTMENT> GetDepartments(ExpressionNode expressionNode);
  29.  
  30. [OperationContract]
  31. DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept);
  32.  
  33. [OperationContract]
  34. bool DeleteDepartment(DTO_TB_DEPARTMENT oDept);
  35.  
  36. [OperationContract]
  37. bool DeleteDeptByLamada(ExpressionNode expressionNode);
  38.  
  39. [OperationContract]
  40. bool UpdateDepartment(DTO_TB_DEPARTMENT oDept);
  41. #endregion
  42.  
  43. #region 角色管理
  44. [OperationContract]
  45. List<DTO_TB_ROLE> GetRoles(ExpressionNode expressionNode);
  46.  
  47. [OperationContract]
  48. DTO_TB_ROLE AddRole(DTO_TB_ROLE oRole);
  49. #endregion
  50.  
  51. #region 菜单管理
  52. [OperationContract]
  53. List<DTO_TB_MENU> GetMenus(ExpressionNode expressionNode);
  54.  
  55. [OperationContract]
  56. DTO_TB_MENU AddMenu(DTO_TB_MENU oMenu);
  57. #endregion
  58. }

1.2 WCF接口实现代码:

 PowerManageWCFService

这里要说明一点,在通过lamada表达式查询的方法里面为什么不直接用Expression<Func<DTO_TB_USERS,bool>>这种类型,而要使用ExpressionNode这种类型的变量呢?

这是因为Expression不支持序列化,无法用于WCF数据的传递。ExpressionNode这个对象的使用需要添加Serialize.Linq这个dll的引用,还好有我们神奇的NuGet,让我们再也不用去网上找一大堆的dll了。

我们公用的增删改查封装到了BaseService这个父类里面。

1.3 BaseService代码

 BaseService

这个父类主要做了两件事:一是MEF的初始化;二是通用增删改查的实现。所有dto对象和领域model的映射都在这里统一管理。

2、UI层代码

UI层里面,为了更好分离代码,我们引入了接口编程的机制,引入了ESTM.Web.IBLL和ESTM.Web.BLL两个项目,如图:

为什么要有这么一个接口层?之前C#进阶系列——MEF实现设计上的“松耦合”(终结篇:面向接口编程)这篇已经做过介绍,对面向接口编程不了解的朋友可以看看。

2.1 ESTM.Web.IBLL代码

这个dll主要定义接口规则。

  1. public interface IPowerManager
  2. {
  3. List<DTO_TB_USERS> GetUsers(Expression<Func<DTO_TB_USERS, bool>> selector = null);
  4.  
  5. DTO_TB_USERS AddUser(DTO_TB_USERS oUser);
  6.  
  7. bool DeleteUser(DTO_TB_USERS oUser);
  8.  
  9. bool UpdateUser(DTO_TB_USERS oUser);
  10.  
  11. bool DeleteUser(Expression<Func<DTO_TB_USERS, bool>> selector = null);
  12.  
  13. List<DTO_TB_DEPARTMENT> GetDepartments(Expression<Func<DTO_TB_DEPARTMENT, bool>> selector = null);
  14.  
  15. DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept);
  16.  
  17. bool DeleteDepartment(DTO_TB_DEPARTMENT oDept);
  18.  
  19. bool DeleteDepartment(Expression<Func<DTO_TB_DEPARTMENT, bool>> selector = null);
  20.  
  21. bool UpdateDepartment(DTO_TB_DEPARTMENT oDept);
  22.  
  23. List<DTO_TB_ROLE> GetRoles(Expression<Func<DTO_TB_ROLE, bool>> selector = null);
  24.  
  25. List<DTO_TB_MENU> GetMenus(Expression<Func<DTO_TB_MENU, bool>> selector = null);
  26.  
  27. }

2.2 ESTM.Web.BLL代码

这个dll用于实现ESTM.Web.IBLL里面的接口方法

 PowerManager : IPowerManager
  1.   public class CreatePowerManagerService
  2. {
  3. private static ServiceReference_PowerManager.PowerManageWCFServiceClient oPowerManagerClient = null;
  4. private static object obj = new object();
  5.  
  6. public static ServiceReference_PowerManager.PowerManageWCFServiceClient GetInstance()
  7. {
  8. lock (obj)
  9. {
  10. if (oPowerManagerClient == null)
  11. {
  12. oPowerManagerClient = new ServiceReference_PowerManager.PowerManageWCFServiceClient();
  13. }
  14. }
  15. return oPowerManagerClient;
  16. }
  17. }

由于是采用的添加服务引用的方式引用的WCF服务,所以在这一层需要添加WCF服务的引用。在实现这部分代码的时候博主遇到过一个问题,在此和朋友们分享一下。由于在WCF服务的设计里面用到了DTO对象,而在ESTM.Web.BLL这个项目里面也要用到DTO,但是添加WCF服务引用的时候默认的是WCF服务里面的DTO,而不是ESTM.Common.DtoModel这个项目的DTO对象,这样就有问题了,每次如果我们需要改动下dto的内容,那么我们就需要更新下服务引用。还好,微软给我们选择的机制,我们来看图

这样就能解决上面的问题了。

2.3 ESTM.Web代码

按照面向接口的机制,ESTM.Web项目是不需要添加ESTM.Web.BLL这个实现层项目引用的,通过MEF动态导入ESTM.Web.BLL里面的对象。我们来看代码:

 PowerManagerController

View页面

 _Layout.cshtml
 Department.cshtml

JS代码我们来看一个页面就好了,其他页面类似:

 DepartmentManage.js

效果图:

在做页面数据更新的时候,博主又遇到一个问题:ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。在此还是记录下解决方案:

在仓储的公共实现类中将

  1.      public virtual IQueryable<TEntity> Entities
  2. {
  3. get { return UnitOfWork.context.Set<TEntity>(); }
  4. }

改成

  1. public virtual IQueryable<TEntity> Entities
  2. {
  3. get { return UnitOfWork.context.Set<TEntity>().AsNoTracking() as IQueryable<TEntity>; }
  4. }

就可以了。

至此,从领域模型到Web前端的代码基本完成,可能很多代码并未完善,比如异常处理、数据验证等。之前写过一篇CS版本的权限系统 系统设计——权限系统,很多朋友找我要过源码,那个时候可能代码都在工作的项目中,没办法抽离出来,在此表示抱歉。现在做了一个BS的,感觉BS比CS界面好看,在这里将源码分享出来,当然这里的代码肯定也不太全,很多没实现的功能还需要自己去实现,但是基本的架子搭起来了,有兴趣可以看看。源码下载

 
分类: .NetBSC#

Web层的搭建的更多相关文章

  1. C#进阶系列——DDD领域驱动设计初探(七):Web层的搭建

    前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码.之前的六篇完成了领域层.应用层.以及基础结构层的部分代码,这篇打算搭建下UI层的代码. DDD领域驱动设计初 ...

  2. DDD领域驱动设计初探(七):Web层的搭建

    前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码.之前的六篇完成了领域层.应用层.以及基础结构层的部分代码,这篇打算搭建下UI层的代码. DDD领域驱动设计初 ...

  3. 微服务迁移记(五):WEB层搭建(5)-集成ueditor编辑器,伪分布式图片上传

    一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...

  4. 微服务迁移记(五):WEB层搭建(1)

    WEB层是最终表现层,注册至注册中心,引用接口层(不需要引用实现层).公共服务层.用户登录使用SpringSecurity,Session保存在redis中,权限管理没有用SpringSecurity ...

  5. 微服务迁移记(五):WEB层搭建(2)-SpringSecurity集成

    一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 接下来,集成SpringSecruity,实现用户 ...

  6. 微服务迁移记(五):WEB层搭建(3)-FreeMarker集成

    一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...

  7. 微服务迁移记(五):WEB层搭建(4)-简单的权限管理

    一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...

  8. IDEA项目搭建二——使用SpringBoot创建Web层

    一.编写底层代码 1.demo-common中创建FormatString类 先在默认com.tyh中创建package命名为common 删除自动生成的app.java,在common包下创建新类 ...

  9. mvc项目架构搭建之UI层的搭建

    项目架构搭建之UI层的搭建 Contents 系列一[架构概览] 0.项目简介 1.项目解决方案分层方案 2.所用到的技术 3.项目引用关系 系列二[架构搭建初步] 4.项目架构各部分解析 5.项目创 ...

随机推荐

  1. css 简单 返回顶部 代码及注释说明

    1. 最简单的静态返回顶部,点击直接跳转页面顶部,常见于固定放置在页面底部返回顶部功能 方法一:用命名锚点击返回到顶部预设的id为top的元素 html代码 <a href="#top ...

  2. Jetty开发指导:Jetty Websocket API

    Jetty WebSocket API使用 Jetty提供了功能更强的WebSocket API,使用一个公共的核心API供WebSockets的服务端和client使用. 他是一个基于WebSock ...

  3. Source not found for StandardEngine(ContainerBase).initInternal() line: 1078

    总是这样 在复制完一个项目,并重新起了个名字后. 再打开网页就怎么也打开不了.   第一反应是tomcat出问题了. 于是有了这样的问题: Source not found for StandardE ...

  4. android开机启动应用和服务

    注冊广播监听开机状态.启动应用和服务等: 监听开机的广播接收器: public class BootCompletedReceiver extends BroadcastReceiver{ @Over ...

  5. MVC的DependencyResolver组件

    MVC的DependencyResolver组件 一.前言 DependencyResolver是MVC中一个重要的组件,从名字可以看出,它负责依赖对象的解析,可以说它是MVC框架内部使用的一个IOC ...

  6. 原创教程“ActionScript3.0游戏中的图像编程”開始连载啦!

            经过近两年的不懈努力,笔者的原创教程"ActionScript3游戏中的图像编程"最终在今日划上了完美的句号!这其中记录着笔者多年来在游戏制作,尤其是其中图像处理方 ...

  7. 状态压缩dp(hdu2167,poj2411)

    hdu2167 http://acm.hdu.edu.cn/showproblem.php?pid=2167 给定一个N*N的板子,里面有N*N个数字,选中一些数字,使得和最大 要求任意两个选中的数字 ...

  8. java 对map排序

    public static Map<String, String> sortMapByKey(Map<String, String> map) { if (map == nul ...

  9. FastDFS源代码分析之tracker协议分析

    本篇博客主要解说fastdfs中tracker协议的解说. fastdfs主要是存储文件.直接把整个文件存储到磁盘上,所以.简单直接.可是也有非常大的局限性. 因此,fastdfs对文件的文件夹设置和 ...

  10. JS window.open()财产

    一. Window 对象 Window 对象是 JavaScript 顶级对象层次. Window 对象表示一个浏览器窗口或帧. Window 在对象 <body> 或 <frame ...