[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权限验 ...
随机推荐
- Css3 权重
Css权重 权重--很多规则应用到同一个元素上时,权重是决定哪个生效的(优先级) 权重等级与权值 行内样式(1000)>ID选择器(100)>类.属性选择器或伪类选择器(10)>元素 ...
- python基础----pymysql模块
安装pymysql ----pip install mysql 步骤: 1.建立连接 指定ip.端口号.密码.账号.数据库 2.建立游标 3.执行sql语句 4.获取结果或提交 5.关闭游标, ...
- dp[2019.5.25]
1.实例计算(写出计算过程): 1)对维数为序列<5, 10, 3, 12, 5, 50, 6>的各矩阵,找出其矩阵链乘积的一个最优加全部括号. 这是一个矩阵连乘问题,基本知识可以参考: ...
- EuRoc V203数据集的坑
EuRoc数据集时间戳问题 以前听别人说过V203序列有问题,今儿仔细看了才发现EuRoc的V203数据集中的左右相机 照片数量不相等,很僵硬,cam0存在大量丢帧,之前一直用单目数据,没什么感觉.. ...
- 刀塔OMG塔防1.26b单机版使用方法
使用方法 1.确保魔兽的版本为1.26以上(低版本会报错),如果版本不对用附件中的版本转换器转一下 2.把 omg.w3x 复制到 魔兽的MAPS文件夹 WarcraftIII 游戏根目录\Maps\ ...
- elasticsearch 的post put 方式的对比 setting mapping设置 - 添加查询数据
1.POST和PUT都可以用于创建 2.PUT是幂等方法,POST不是.所以post用户更新,put用于新增比较合适. 参考:https://yq.aliyun.com/articles/366099 ...
- jqGrid只向服务器请求一次的设置
也就是说,在表格初始化时请求一次服务器,以后翻页就不再请求服务器,翻页的也只是初始化数据. 一次复制别人的代码时,一直不知道为什么翻页不请求服务器. 搞到人都爆炸,原来只是一个设置的地方. loado ...
- js函数(3)
8.5 作为命名空间的函数 即定义一个函数用做临时的命名空间,在这个命名空间内定义的变量都不会污染到全局命名空间. 将一段代码封装在函数内部,然后调用这个函数.这样全局变量就变成了函数内部的局部变量: ...
- Vue.directive()的用法和实例
官网实例: https://cn.vuejs.org/v2/api/#Vue-directive https://cn.vuejs.org/v2/guide/custom-directive.html ...
- java 分解整数 【个 十 百 千】,获得个位、十位、百位数字
求一个数数的个位数,十位数,百位数及千位: int num = 53; int g = (num / 1) % 10; //个位 int s = (num / 10) % 10; //十位 int ...