Web层的搭建
Web层的搭建
前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码。之前的六篇完成了领域层、应用层、以及基础结构层的部分代码,这篇打算搭建下UI层的代码。
DDD领域驱动设计初探系列文章:
- C#进阶系列——DDD领域驱动设计初探(一):聚合
- C#进阶系列——DDD领域驱动设计初探(二):仓储Repository(上)
- C#进阶系列——DDD领域驱动设计初探(三):仓储Repository(下)
- C#进阶系列——DDD领域驱动设计初探(四):WCF搭建
- C#进阶系列——DDD领域驱动设计初探(五):AutoMapper使用
- C#进阶系列——DDD领域驱动设计初探(六):领域服务
- C#进阶系列——DDD领域驱动设计初探(七):Web层的搭建
一、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/
二、代码示例
上篇完成了WCF的设计代码,但是具体的业务逻辑的代码还没有,我们先来实现具体业务的CURD代码。
1、WCF代码
1.1 WCF服务业务接口代码

/// <summary>
/// 权限管理模块接口契约
/// </summary>
[ServiceContract]
[ServiceInterface]
public interface IPowerManageWCFService
{ #region 用户管理
[OperationContract]
List<DTO_TB_USERS> GetUsers(ExpressionNode expressionNode); [OperationContract]
DTO_TB_USERS AddUser(DTO_TB_USERS oUser); [OperationContract]
bool DeleteUser(DTO_TB_USERS oUser); [OperationContract]
bool DeleteUserByLamada(ExpressionNode expressionNode); [OperationContract]
bool UpdateUser(DTO_TB_USERS oUser);
#endregion #region 部门管理
[OperationContract]
List<DTO_TB_DEPARTMENT> GetDepartments(ExpressionNode expressionNode); [OperationContract]
DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept); [OperationContract]
bool DeleteDepartment(DTO_TB_DEPARTMENT oDept); [OperationContract]
bool DeleteDeptByLamada(ExpressionNode expressionNode); [OperationContract]
bool UpdateDepartment(DTO_TB_DEPARTMENT oDept);
#endregion #region 角色管理
[OperationContract]
List<DTO_TB_ROLE> GetRoles(ExpressionNode expressionNode); [OperationContract]
DTO_TB_ROLE AddRole(DTO_TB_ROLE oRole);
#endregion #region 菜单管理
[OperationContract]
List<DTO_TB_MENU> GetMenus(ExpressionNode expressionNode); [OperationContract]
DTO_TB_MENU AddMenu(DTO_TB_MENU oMenu);
#endregion
}

1.2 WCF接口实现代码:
这里要说明一点,在通过lamada表达式查询的方法里面为什么不直接用Expression<Func<DTO_TB_USERS,bool>>这种类型,而要使用ExpressionNode这种类型的变量呢?
这是因为Expression不支持序列化,无法用于WCF数据的传递。ExpressionNode这个对象的使用需要添加Serialize.Linq这个dll的引用,还好有我们神奇的NuGet,让我们再也不用去网上找一大堆的dll了。

我们公用的增删改查封装到了BaseService这个父类里面。
1.3 BaseService代码
这个父类主要做了两件事:一是MEF的初始化;二是通用增删改查的实现。所有dto对象和领域model的映射都在这里统一管理。
2、UI层代码
UI层里面,为了更好分离代码,我们引入了接口编程的机制,引入了ESTM.Web.IBLL和ESTM.Web.BLL两个项目,如图:

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

public interface IPowerManager
{
List<DTO_TB_USERS> GetUsers(Expression<Func<DTO_TB_USERS, bool>> selector = null); DTO_TB_USERS AddUser(DTO_TB_USERS oUser); bool DeleteUser(DTO_TB_USERS oUser); bool UpdateUser(DTO_TB_USERS oUser); bool DeleteUser(Expression<Func<DTO_TB_USERS, bool>> selector = null); List<DTO_TB_DEPARTMENT> GetDepartments(Expression<Func<DTO_TB_DEPARTMENT, bool>> selector = null); DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept); bool DeleteDepartment(DTO_TB_DEPARTMENT oDept); bool DeleteDepartment(Expression<Func<DTO_TB_DEPARTMENT, bool>> selector = null); bool UpdateDepartment(DTO_TB_DEPARTMENT oDept); List<DTO_TB_ROLE> GetRoles(Expression<Func<DTO_TB_ROLE, bool>> selector = null); List<DTO_TB_MENU> GetMenus(Expression<Func<DTO_TB_MENU, bool>> selector = null); }

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

public class CreatePowerManagerService
{
private static ServiceReference_PowerManager.PowerManageWCFServiceClient oPowerManagerClient = null;
private static object obj = new object(); public static ServiceReference_PowerManager.PowerManageWCFServiceClient GetInstance()
{
lock (obj)
{
if (oPowerManagerClient == null)
{
oPowerManagerClient = new ServiceReference_PowerManager.PowerManageWCFServiceClient();
}
}
return oPowerManagerClient;
}
}

由于是采用的添加服务引用的方式引用的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里面的对象。我们来看代码:
View页面
JS代码我们来看一个页面就好了,其他页面类似:
效果图:



在做页面数据更新的时候,博主又遇到一个问题:ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。在此还是记录下解决方案:
在仓储的公共实现类中将
public virtual IQueryable<TEntity> Entities
{
get { return UnitOfWork.context.Set<TEntity>(); }
}
改成
public virtual IQueryable<TEntity> Entities
{
get { return UnitOfWork.context.Set<TEntity>().AsNoTracking() as IQueryable<TEntity>; }
}
就可以了。
至此,从领域模型到Web前端的代码基本完成,可能很多代码并未完善,比如异常处理、数据验证等。之前写过一篇CS版本的权限系统 系统设计——权限系统,很多朋友找我要过源码,那个时候可能代码都在工作的项目中,没办法抽离出来,在此表示抱歉。现在做了一个BS的,感觉BS比CS界面好看,在这里将源码分享出来,当然这里的代码肯定也不太全,很多没实现的功能还需要自己去实现,但是基本的架子搭起来了,有兴趣可以看看。源码下载
Web层的搭建的更多相关文章
- C#进阶系列——DDD领域驱动设计初探(七):Web层的搭建
前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码.之前的六篇完成了领域层.应用层.以及基础结构层的部分代码,这篇打算搭建下UI层的代码. DDD领域驱动设计初 ...
- DDD领域驱动设计初探(七):Web层的搭建
前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码.之前的六篇完成了领域层.应用层.以及基础结构层的部分代码,这篇打算搭建下UI层的代码. DDD领域驱动设计初 ...
- 微服务迁移记(五):WEB层搭建(5)-集成ueditor编辑器,伪分布式图片上传
一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...
- 微服务迁移记(五):WEB层搭建(1)
WEB层是最终表现层,注册至注册中心,引用接口层(不需要引用实现层).公共服务层.用户登录使用SpringSecurity,Session保存在redis中,权限管理没有用SpringSecurity ...
- 微服务迁移记(五):WEB层搭建(2)-SpringSecurity集成
一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 接下来,集成SpringSecruity,实现用户 ...
- 微服务迁移记(五):WEB层搭建(3)-FreeMarker集成
一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...
- 微服务迁移记(五):WEB层搭建(4)-简单的权限管理
一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...
- IDEA项目搭建二——使用SpringBoot创建Web层
一.编写底层代码 1.demo-common中创建FormatString类 先在默认com.tyh中创建package命名为common 删除自动生成的app.java,在common包下创建新类 ...
- mvc项目架构搭建之UI层的搭建
项目架构搭建之UI层的搭建 Contents 系列一[架构概览] 0.项目简介 1.项目解决方案分层方案 2.所用到的技术 3.项目引用关系 系列二[架构搭建初步] 4.项目架构各部分解析 5.项目创 ...
随机推荐
- html学习 - 自己主动跳转与自己主动刷新
自己主动刷新 事实上自己主动刷新和跳转没啥差别,刷新就是跳转到本地址. 有几种办法,首先是直接在html的<head>标签里加入以下的代码. html代码 代码都放在<head> ...
- Android-它们的定义Notification
Android-它们的定义Notification 2014年4月26日 消息栏的消息,想必各位Android发烧友非常清楚知道是什么,比方我们下载了一个应用,它可能会定时推送些消息到我们的手机中. ...
- Android开发之文件下载,状态时显示下载进度,点击自动安装
在进行软件升级时,需要进行文件下载,在这里实现自定义的文件下载,并在状态栏显示下载进度,下载完成后,点击触发安装. 效果如图: 用于下载文件和显示现在进度的线程类如下: [java] view pl ...
- 【翻译】Why JavaScript Is and Will Continue to Be the First Choice of Programmers
花费2半小时,那么最终会被翻译.假设有问题,请提出,毕竟,自己的6不超过级别. 附加链接 Why JavaScript Is and Will Continue to Be the First Cho ...
- wxWidgets刚開始学习的人导引(1)——前言
wxWidgets刚開始学习的人导引全文件夹 PDF版及附件下载 1 前言2 下载.安装wxWidgets3 wxWidgets应用程序初体验4 wxWidgets学习资料及利用方法指导5 用wx ...
- import android.provider.Telephony cannot be resolved
android.provider.Telephony is hidden. http://androidxref.com/4.0.3_r1/xref/frameworks/base/core/java ...
- SQLite Code配置DbConfiguration
[DbConfigurationType(typeof(SQLiteConfiguration))] public partial class rsapiEntities : DbContext { ...
- Google Maps Android API v2 (4)- 地图类型
地图类型 地图内的谷歌地图的Android API的种类有很多.地图的类型管辖地图的整体代表性.例如,地图集通常包含政治地图,专注于显示边界和道路地图,显示了一个城市或地区的所有道路. Android ...
- NET WEB
.NET WEB程序员需要掌握的技能 2015-12-28 08:50 by 敏捷的水, 3997 阅读, 66 评论, 收藏, 编辑 本来这个是我给我们公司入职的新人做一个参考,由于 @张善友 老师 ...
- 构建安全的Xml Web Service系列之初探使用Soap头
原文:构建安全的Xml Web Service系列之初探使用Soap头 Xml Web Service 从诞生那天就说自己都么都么好,还津津乐道的说internet也会因此而进入一个新纪元,可5年多来 ...