C#进阶系列——DDD领域驱动设计初探(七):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服务业务接口代码

复制代码
    /// <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接口实现代码:

  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主要定义接口规则。

复制代码
 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里面的接口方法

  PowerManager : IPowerManager
复制代码
  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里面的对象。我们来看代码:

  PowerManagerController

View页面

  _Layout.cshtml
  Department.cshtml

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

  DepartmentManage.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界面好看,在这里将源码分享出来,当然这里的代码肯定也不太全,很多没实现的功能还需要自己去实现,但是基本的架子搭起来了,有兴趣可以看看。






本文转自懒得安分博客园博客,原文链接:http://www.cnblogs.com/landeanfen/p/4920577.html,如需转载请自行联系原作者

目录
相关文章
|
8月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
221 3
|
3月前
|
API C#
异步轮询 Web API 的实现与 C# 示例
异步轮询 Web API 的实现与 C# 示例
94 0
|
5月前
|
前端开发 JavaScript C#
C#开发者的新天地:Blazor如何颠覆传统Web开发,打造下一代交互式UI?
【8月更文挑战第28天】Blazor 是 .NET 生态中的革命性框架,允许使用 C# 和 .NET 构建交互式 Web UI,替代传统 JavaScript。本文通过问答形式深入探讨 Blazor 的基本概念、优势及应用场景,并指导如何开始使用 Blazor。Blazor 支持代码共享、强类型检查和丰富的生态系统,简化 Web 开发流程。通过简单的命令即可创建 Blazor 应用,并利用其组件化和数据绑定特性快速搭建界面。无论对于 .NET 还是 Web 开发者,Blazor 都是一个值得尝试的新选择。
205 1
|
5月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
451 0
|
5月前
|
开发者 Java Spring
JSF 牵手社交登录,如魔法风暴席卷 Web 世界,开启震撼便捷登录之旅!
【8月更文挑战第31天】在互联网时代,便捷登录成为用户的核心需求。社交登录凭借其便捷性、安全性和社交化的特点,在各类Web应用中广泛应用。JavaServer Faces(JSF),作为一款流行的Java Web框架,能够轻松集成社交登录功能,显著提升用户体验。本文详细介绍社交登录的优势,并提供两种JSF集成社交登录的常见方法:一是利用Spring Social等第三方库简化开发;二是自行实现社交登录流程。开发者可根据项目需求选择适合的方案。
52 0
|
6月前
|
SQL 安全 Go
SQL注入不可怕,XSS也不难防!Python Web安全进阶教程,让你安心做开发!
【7月更文挑战第26天】在 Web 开发中, SQL 注入与 XSS 攻击常令人担忧, 但掌握正确防御策略可化解风险. 对抗 SQL 注入的核心是避免直接拼接用户输入至 SQL 语句. 使用 Python 的参数化查询 (如 sqlite3 库) 和 ORM 框架 (如 Django, SQLAlchemy) 可有效防范. 防范 XSS 攻击需严格过滤及转义用户输入. 利用 Django 模板引擎自动转义功能, 或手动转义及设置内容安全策略 (CSP) 来增强防护. 掌握这些技巧, 让你在 Python Web 开发中更加安心. 安全是个持续学习的过程, 不断提升才能有效保护应用.
60 1
|
5月前
|
Java 数据库连接 C#
Visual Studio C# 多环境配置 Web.config
Visual Studio C# 多环境配置 Web.config
70 0
|
6月前
|
缓存 JavaScript 前端开发
JavaScript进阶 - Web Workers与Service Worker
【7月更文挑战第4天】JavaScript的Web Workers和Service Worker增强了Web性能。Web Workers处理后台多线程,减轻主线程负担,但通信有开销,受同源策略限制。Service Worker则用于离线缓存和推送通知,需管理其生命周期、更新策略,并确保安全。两者都带来了挑战,但也极大提升了用户体验。通过理解和优化,开发者能构建更高效、安全的Web应用。
148 2
|
6月前
|
前端开发 开发者 Python
从零到一:Python Web框架中的模板引擎入门与进阶
【7月更文挑战第20天】模板引擎如Jinja2在Python Web开发中连接后端与前端,提高代码可读性和协作效率。Flask默认集成Jinja2,提供条件语句、循环、宏和模板继承等功能。例如,创建一个简单Flask应用,渲染&quot;Hello, World!&quot;,并展示如何使用条件语句和循环处理数据。通过宏定义重用代码,模板继承实现页面结构共享。学习模板引擎能提升开发效率和项目质量。
69 0
|
6月前
|
SQL 前端开发 数据库
Python Web开发进阶之路:从模板引擎到ORM的全面掌握
【7月更文挑战第19天】在Python Web开发中,提升技能的关键是理解和运用模板引擎(如Jinja2)与ORM技术。模板引擎,如在Flask中使用的Jinja2,使前端HTML与后端逻辑分离,便于维护。例如,通过路由函数`show_posts()`和`render_template()`呈现文章列表模板,用Jinja2的`for`循环展示内容。ORM,如SQLAlchemy,提供Pythonic的数据库操作,将表映射为类,SQL转化为方法调用。在博客系统中,定义Post模型并与数据库交互,展示了ORM简化数据管理的优势。通过实践这些工具,开发者能更好地驾驭复杂的Web项目。
60 0