[Abp vNext微服务实践] - 业务开发
前几篇分别介绍了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微服务实践] - 业务开发的更多相关文章
- [Abp vNext微服务实践] - 文章目录
简介 ABP vNext是volosoft的新一代框架,ABP(vNext)完全使用.NET CORE和DDD(领域驱动)打造,目前GitHub已有6K+次提交,发布版本超过40次,Nuget包下载量 ...
- [Abp vNext微服务实践] - 前后端分类
一.前景 abp vNext是ABP 开源 Web应用程序框架,是abp的新一代开源web框架.框架完美的集成.net core.identity server4等开源框架,适用于构建web应用程序和 ...
- [Abp vNext微服务实践] - 框架分析
一.简介 abp vNext新框架的热度一直都很高,于是最近上手将vNext的微服务Demo做了一番研究.我的体验是,vNext的微服务架构确实比较成熟,但是十分难以上手,对于没有微服务开发经验的.n ...
- [Abp vNext微服务实践] - 添加中文语言
简介 abp vNext中提供了多语言功能,默认语言是英文,没有提供中文语言包.在业务开发中,定义权限后需要用中文的备注提供角色选择,本篇将介绍如何在abp vNext中加入中文语言. step1:添 ...
- [Abp vNext微服务实践] - 服务通讯
简介 服务通讯是微服务架构中必不可少的功能,服务通讯的效率决定了微服务架构的优略.常用的微服务通讯策略有两种,分别是rpc.http,其中rpc以gRpc框架为代表使用者最多.abp vNext微服务 ...
- [Abp vNext微服务实践] - vue-element-admin管理Identity
一.简介 abp vNext微服务框架中已经提供通用权限和用户角色管理模块,管理UI使用的是MVC模式,不适用于国内主打的MVVM开发模式.在前端框架选型后笔者决定改造abp vNext微服务框架中原 ...
- [Abp vNext微服务实践] - 启动流程
前几篇分别介绍了abp vNext微服务框架和微服务CI/CD环境搭建,本篇开始介绍vNext微服务框架的开发环境搭建. 环境准备 官方介绍的系统架构图如下: 上图中身份服务和网关服务已经集成在系统中 ...
- [Abp vNext微服务实践] - 租户登录
简介 Abp vNext微服务授权验证基于ids4,实现租户登录需要在授权服务中获取token,和之前的介绍的登录方式一样,只是多了tenant参数.本篇将介绍在Abp vNext授权服务中启用多租户 ...
- [Abp vNext微服务实践] - vue-element-admin登录二
简介: Vue Element Admin是基于vue.element ui开发的后台管理ui,abp vNext是abp新一代微服务框架.本篇将会介绍如何改造Vue Element Admin权限验 ...
随机推荐
- SNIPER-MXNet中出现ValueError: could not broadcast input array from shape (XXX,5) into shape (100,5)
这是关于标签数量的问题,搜索"100," ,其中与读标签框有关,或者与标签匹配有关的,全部改到大于“图片中最多有的标签数量”即可.
- 部署zabbix监控平台(源码安装)
案例:部署Zabbix监控平台 1 问题 本案例要求部署一台Zabbix监控服务器,一台被监控主机,为进一步执行具体的监控任务做准备: 安装LNMP环境 源码安装Zabbix 安装监控端主机,修改基本 ...
- YUV RGB 格式转换
第一个公式是RGB转YUV(范围0-255)时用的,第二个公式是用在YUV转换RGB(范围0-255)时用的.1. Y = ; U = -; V = ; 黑色:Y=16 ,U= V =128 红色:Y ...
- 【VS开发】CString 转为 char *方法大全
[VS开发]CString 转为 char *方法大全 标签(空格分隔): [VS开发] 方法1: CString strTemp; char szTemp[128]; strTemp = _T(&q ...
- java_guide_类加载器
类加载器总结 JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader ...
- 破周三,前不着村后不着店的,只好学pandas了,你该这么学,No.9
如果图片无法观看,请移步 https://blog.csdn.net/hihell 周三了,一个星期最难的一天 大中间的,今天还这么热 5月份,36度的高温 天空飘过几个字 屋里学pandas最得劲 ...
- jqGrid清空表格
$("#jqGrid").jqGrid("setGridParam",{ datatype:'local', data : [], page:1 }).trig ...
- jdk1.8 -- 自定义FunctionInterface
一.自定义函数的理解 对于java提供的一些函数,用lambda表达式是可以解决一些问题的,但是在对于一些比较复杂的数据类型在处理时,可能会有些力不从心了,但是 我们可以通过自定义的一些函数,通过使用 ...
- thinkphp中return $this->fetch的问题
当reture放在foreach循环外面,也就是现在的位置的时候,会报错.如下图.但当return放在foreach语句里面的时候就不会报错,但因为return会结束语句,这也就导致了foreach只 ...
- LUA的table实现
数据结构 下面的结构体是lua中所定义的table typedef struct Table { CommonHeader; lu_byte flags; /* 1<<p means ta ...