前几篇分别介绍了abp vNext微服务框架、开发环境搭建和vue element admin前端框架接入,在vue element admin中实现用户角色管理基本功能后就可以开始进行业务开发了,本篇会详细的介绍如何在abp vNext中开发业务接口和前端页面实现。

业务接口开发

业务接口就是针对业务api接口,通过abp vNext微服务中实现并发布业务接口后,前端获取接口并进行界面开发,如此就实现了abp vNext微服务的前后端分离开发。

step1:创建实体(model)

abp vNext微服务框架中的业务开发同样采用了经典的ddd架构风格和ef core 的code first模式,所以一切的业务都从领域模型(domain)开始。创建数据字典模型如下:

    public class DataDictionary : AuditedAggregateRoot<Guid>,ISoftDelete
{
[NotNull]
public string Name { get; set; } public string Code { get; set; } [NotNull]
public string FullName { get; set; } public Guid? CategoryID { get; set; } public string Notes { get; set; } public Guid? PID { get; set; } [NotNull]
public int SEQ { get; set; } public bool IsEdit { get; set; } public bool IsDeleted { get; set; }
}

step2:加入AbpDbContext:

public DbSet<DataDictionary> Dictionary { get; set; }

step3:构建ef实体:

            builder.Entity<DataDictionary>(b =>
{
b.ToTable("Dictionary"); b.ConfigureConcurrencyStamp();
b.ConfigureExtraProperties();
b.ConfigureAudited(); b.Property(x => x.Name).IsRequired().HasMaxLength(ProductConsts.MaxNameLength);
b.Property(x => x.Code).HasMaxLength(ProductConsts.MaxCodeLength);
b.Property(x => x.FullName).IsRequired().HasMaxLength(ProductConsts.MaxFullNameLength);
b.Property(x => x.Notes).HasMaxLength(ProductConsts.MaxNotesLength);
b.Property(x => x.SEQ).IsRequired(); b.HasIndex(q => q.Code);
b.HasIndex(q => q.Name);
b.HasIndex(q => q.CategoryID);
});

step4:使用ef迁移数据库:

 Add-Migration
Update-Database

查看输出日志是否成功迁移。

创建数据字典应用服务接口

step5:创建数据字典接口和dto如下:

    public interface IDictionaryAppService : IApplicationService
{
Task<PagedResultDto<DictionaryDto>> GetAll(GetDictionaryInputDto input); Task<DictionaryDto> Get(Guid id); Task<DictionaryDto> Create(CreateDictionaryDto input); Task<DictionaryDto> Update(Guid id, UpdateDictionary input); Task Delete(List<Guid> ids);
}
    public class CreateDictionaryDto
{
[Required]
[StringLength(ProductConsts.MaxNameLength)]
public string Name { get; set; } [StringLength(ProductConsts.MaxCodeLength)]
public string Code { get; set; } public Guid? CategoryID { get; set; } [StringLength(ProductConsts.MaxNotesLength)]
public string Notes { get; set; } public Guid? PID { get; set; } public int SEQ { get; set; } public bool IsEdit { get; set; }
}
    public class DictionaryDto : AuditedEntityDto<Guid>
{
public string Name { get; set; } public string Code { get; set; } public string FullName { get; set; } public Guid? CategoryID { get; set; } public string Notes { get; set; } public Guid? PID { get; set; } public int SEQ { get; set; } public bool IsEdit { get; set; }
}
    public class GetDictionaryInputDto: PagedAndSortedResultRequestDto
{
public string Filter { get; set; } public Guid CategoryID { get; set; }
}
    public class UpdateDictionary
{
[StringLength(ProductConsts.MaxNotesLength)]
public string Notes { get; set; } public Guid? PID { get; set; } public int SEQ { get; set; }
}

实现数据字典应用服务

step6:应用层实现如下:

继承基类:

public class DictionaryAppService : ApplicationService, IDictionaryAppService

注入仓储:

        private readonly IRepository<DataDictionary, Guid> _repository;

     public DictionaryAppService(
IRepository<DataDictionary, Guid> repository)
{
_repository = repository;
}

实现接口

新增:

        public async Task<DictionaryDto> Create(CreateDictionaryDto input)
{
var existingDic = await _repository.FirstOrDefaultAsync(d => d.Name == input.Name);
if (existingDic != null)
{
throw new BusinessException("名称: "+input.Name+"已存在");
}var result = await _repository.InsertAsync(new DataDictionary
{
Id = GuidGenerator.Create(),
Name = input.Name,
Code = input.Code,
FullName = input.Name,
CategoryID = input.CategoryID,
Notes = input.Notes,
PID = input.PID,
SEQ = input.SEQ,
IsEdit=input.IsEdit
}); return ObjectMapper.Map<DataDictionary, DictionaryDto>(result);
}

删除:

        public async Task Delete(List<Guid> ids)
{
foreach (var id in ids)
{
await _repository.DeleteAsync(id);
}
}

查询:

        public async Task<DictionaryDto> Get(Guid id)
{
var query = await _repository.GetAsync(id);
var dto = ObjectMapper.Map<DataDictionary, DictionaryDto>(query);return dto;
} public async Task<PagedResultDto<DictionaryDto>> GetAll(GetDictionaryInputDto input)
{
var query = _repository
.Where(d => d.CategoryID == input.CategoryID)
.WhereIf(!string.IsNullOrEmpty(input.Filter), d => d.Name.Contains(input.Filter) ||
d.Code.Contains(input.Filter)); var items = await query.OrderBy(input.Sorting ?? "SEQ")
.Skip(input.SkipCount)
.Take(input.MaxResultCount).ToListAsync(); var totalCount = await query.CountAsync();
var dtos = ObjectMapper.Map<List<DataDictionary>, List<DictionaryDto>>(items);return new PagedResultDto<DictionaryDto>(totalCount, dtos);
}

修改:

        public async Task<DictionaryDto> Update(Guid id, UpdateDictionary input)
{var dic = await _repository.GetAsync(id);
dic.Notes = input.Notes;
dic.SEQ = input.SEQ; return ObjectMapper.Map<DataDictionary, DictionaryDto>(dic);
}

增加数据字典权限

step7:权限

ProductManagementPermissions中增加静态类DataDictionary:

        public static class DataDictionary
{
public const string Default = BasicDataManagement + ".DataDictionary";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
}

step8:构造权限

ProductManagementPermissionDefinitionProvider中增加dataDictionary:

            var dataDictionary = basicDataManagementGroup.AddPermission(ProductManagementPermissions.DataDictionary.Default, L("DataDictionary"));
dataDictionary.AddChild(ProductManagementPermissions.DataDictionary.Create, L("Permission:Create"));
dataDictionary.AddChild(ProductManagementPermissions.DataDictionary.Delete, L("Permission:Delete"));
dataDictionary.AddChild(ProductManagementPermissions.DataDictionary.Update, L("Permission:Edit"));

增加完成后在数据字典应用服务中分别加上权限过滤器

[Authorize(ProductManagementPermissions.DataDictionary.Default)]
[Authorize(ProductManagementPermissions.DataDictionary.Create)]
[Authorize(ProductManagementPermissions.DataDictionary.Delete)]
[Authorize(ProductManagementPermissions.DataDictionary.Update)]

数据字典DTO映射

step9:ProductManagementApplicationAutoMapperProfile中增加数据字典模型-Dto映射:

          CreateMap<DataDictionary, DictionaryDto>();

数据字典web api实现

step10:abp vNext中没有使用原先的应用服务动态api,现在api需要在控制器中实现

    [RemoteService]
[Area("basicData")]
[Route("api/basicData/dataDictionary")]
public class DataDictionaryController : AbpController, IDictionaryAppService
{
private readonly IDictionaryAppService _dictionaryAppService; public DataDictionaryController(IDictionaryAppService dictionaryAppService)
{
_dictionaryAppService = dictionaryAppService;
} [HttpPost]
public Task<DictionaryDto> Create(CreateDictionaryDto input)
{
return _dictionaryAppService.Create(input);
} [HttpPost]
[Route("Delete")]
public Task Delete(List<Guid> ids)
{
return _dictionaryAppService.Delete(ids);
} [HttpGet]
[Route("{id}")]
public Task<DictionaryDto> Get(Guid id)
{
return _dictionaryAppService.Get(id);
} [HttpGet]
[Route("all")]
public Task<PagedResultDto<DictionaryDto>> GetAll(GetDictionaryInputDto input)
{
return _dictionaryAppService.GetAll(input);
} [HttpPut]
[Route("{id}")]
public Task<DictionaryDto> Update(Guid id, UpdateDictionary input)
{
return _dictionaryAppService.Update(id, input);
}
}

swagger文档

总结

abp vNext的业务开发模式并没有做太多改动,虽然接口开发的过程有些繁琐,但是对于业务拆分和模型解耦来说是非常有必要的。ddd的架构风格让开发人员无需依赖于sql语法,可以使用抽象的仓储进行轻松高效的查询,这对于代码维护和项目交接来说是十分幸运的。此外,abp vNext还将身份、权限、模型验证、异常处理等进行了完美封装,使得开发人员可以专注于业务开发。

文章目录:https://www.cnblogs.com/william-xu/p/12047529.html

[Abp vNext微服务实践] - 业务开发的更多相关文章

  1. [Abp vNext微服务实践] - 文章目录

    简介 ABP vNext是volosoft的新一代框架,ABP(vNext)完全使用.NET CORE和DDD(领域驱动)打造,目前GitHub已有6K+次提交,发布版本超过40次,Nuget包下载量 ...

  2. [Abp vNext微服务实践] - 前后端分类

    一.前景 abp vNext是ABP 开源 Web应用程序框架,是abp的新一代开源web框架.框架完美的集成.net core.identity server4等开源框架,适用于构建web应用程序和 ...

  3. [Abp vNext微服务实践] - 框架分析

    一.简介 abp vNext新框架的热度一直都很高,于是最近上手将vNext的微服务Demo做了一番研究.我的体验是,vNext的微服务架构确实比较成熟,但是十分难以上手,对于没有微服务开发经验的.n ...

  4. [Abp vNext微服务实践] - 添加中文语言

    简介 abp vNext中提供了多语言功能,默认语言是英文,没有提供中文语言包.在业务开发中,定义权限后需要用中文的备注提供角色选择,本篇将介绍如何在abp vNext中加入中文语言. step1:添 ...

  5. [Abp vNext微服务实践] - 服务通讯

    简介 服务通讯是微服务架构中必不可少的功能,服务通讯的效率决定了微服务架构的优略.常用的微服务通讯策略有两种,分别是rpc.http,其中rpc以gRpc框架为代表使用者最多.abp vNext微服务 ...

  6. [Abp vNext微服务实践] - vue-element-admin管理Identity

    一.简介 abp vNext微服务框架中已经提供通用权限和用户角色管理模块,管理UI使用的是MVC模式,不适用于国内主打的MVVM开发模式.在前端框架选型后笔者决定改造abp vNext微服务框架中原 ...

  7. [Abp vNext微服务实践] - 启动流程

    前几篇分别介绍了abp vNext微服务框架和微服务CI/CD环境搭建,本篇开始介绍vNext微服务框架的开发环境搭建. 环境准备 官方介绍的系统架构图如下: 上图中身份服务和网关服务已经集成在系统中 ...

  8. [Abp vNext微服务实践] - 租户登录

    简介 Abp vNext微服务授权验证基于ids4,实现租户登录需要在授权服务中获取token,和之前的介绍的登录方式一样,只是多了tenant参数.本篇将介绍在Abp vNext授权服务中启用多租户 ...

  9. [Abp vNext微服务实践] - vue-element-admin登录二

    简介: Vue Element Admin是基于vue.element ui开发的后台管理ui,abp vNext是abp新一代微服务框架.本篇将会介绍如何改造Vue Element Admin权限验 ...

随机推荐

  1. dp[2019.5.25]

    1.实例计算(写出计算过程): 1)对维数为序列<5, 10, 3, 12, 5, 50, 6>的各矩阵,找出其矩阵链乘积的一个最优加全部括号. 这是一个矩阵连乘问题,基本知识可以参考: ...

  2. Path环境变量的作用

    作用: 当我们要求系统运行一个程序(例如a.exe)而没有告诉它程序所在的完整路径时,系统会先在当前目录寻找是否存在a.exe,如果找到,直接运行:如果没有找到,会去path路径下面找.设置path, ...

  3. 机器学习笔记——k-近邻算法(一)简单代码

    一 import numpy as np ##初始化数据 T = [[3, 104, -1], [2, 100, -1], [1, 81, -1], [101, 10, 1], [99, 5, 1], ...

  4. 02.02 lamp环境搭建笔记

    lamp环境 在linux中安装 apache.mysql.php三种软件环境,同时需要安装他 某些插件. cp /etc/apt/sources.list /etc/apt/sources.list ...

  5. A+B Problem Plus and A-B Problem Plus and A*B Problem Plus

    //we have defined the necessary header files here for this problem. //If additional header files are ...

  6. WEB渗透技术之浅析路径遍历

    1. 发送 http://www.nuanyue.com/getfile=image.jgp 当服务器处理传送过来的image.jpg文件名后,Web应用程序即会自动添加完整路径,形如“d://sit ...

  7. Java编程思想(四)初始化和清除

    4.1用构建器自动初始化 若某个类中有一个构建器,那么在创建对象时,Java会自动调用哪个构建器    在Java中构建器的名字必须与类名相同,这样可以保证这样一个方法惠子初始化期间自动调用: 利用构 ...

  8. Java 之前总结

    写Java程序 1使用记事本,编写代码 2命名为文件里的类名称相一致 “.java” 3编译编译器创建class文件 编译 打开命令行窗口,进入Java文件所在的目录,执行命令:javac Welco ...

  9. idea调试框架时如何能够进入maven依赖包的源码

    最近用idea使用spring security做登录与权限控制,在调试过程中碰到问题,经常需要断点追踪源码,深入查看其中问题.但是maven中引用的包,进入后都是.class文件,非源码.导致查看时 ...

  10. Linux基础 目录

    一,linux入门介绍 二,界面目录介绍 三,vim使用 四,文件管理. 文件夹管理. 五.用户创建流程.用户管理 .组管理 六.权限管理.软连接/硬链接 七.磁盘管理 八.软件包的管理 九.系统服务 ...