本文以 Module 模块为例,说明如何新建模块实体类、输入输出 DTO 以及模块服务接口。
约定:Module 可替换为实际业务模块名称。
1. 新建模块实体类 在以下目录中新建 Module 目录:
1 MyCompanyName.MyProjectName.Api.Contracts\Domain
然后在 Module 目录下新建实体类 ModuleEntity。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 using System;using FreeSql.DataAnnotations;using ZhonTai.Admin.Core.Entities;using MyCompanyName.MyProjectName.Api.Contracts.Core.Consts;namespace MyCompanyName.MyProjectName.Api.Contracts.Domain.Module ;[Table(Name = DbConsts.TableNamePrefix + "module" ) ] [Index("idx_{tablename}_01" , nameof(TenantId) + "," + nameof(Name), true) ] public partial class ModuleEntity : EntityTenant { [Column(StringLength = 50) ] public string Name { get ; set ; } }
约定说明
实体类以 Entity 结尾,例如:ModuleEntity。
表名和索引采用下划线命名法。
表名前缀统一使用 DbConsts.TableNamePrefix。
索引名称以 idx 开头。
继承 EntityTenant 后,查询数据时会自动根据租户编号 TenantId 进行数据筛选。
2. 新建输入输出 DTO 在以下目录下新建 Input 和 Output 目录:
1 MyCompanyName.MyProjectName.Api.Contracts\Services
推荐目录结构如下:
1 2 MyCompanyName.MyProjectName.Api.Contracts\Services\Module\Input MyCompanyName.MyProjectName.Api.Contracts\Services\Module\Output
2.1 新建添加输入 DTO 在 Input 目录下新建 ModuleAddInput。
1 2 3 4 5 6 7 8 9 10 11 12 namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input ;public class ModuleAddInput { public string Name { get ; set ; } }
2.2 新建修改输入 DTO 在 Input 目录下新建 ModuleUpdateInput。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 using System.ComponentModel.DataAnnotations;using ZhonTai.Admin.Core.Validators;namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input ;public partial class ModuleUpdateInput : ModuleAddInput { [Required ] [ValidateRequired("请选择模块" ) ] public long Id { get ; set ; } }
2.3 新建分页查询输入 DTO 在 Input 目录下新建 ModuleGetPageInput。
1 2 3 4 5 6 7 8 9 10 11 12 namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input ;public partial class ModuleGetPageInput { public string Name { get ; set ; } }
2.4 新建模块详情输出 DTO 在 Output 目录下新建 ModuleGetOutput。
1 2 3 4 5 6 7 8 9 10 using MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Output ;public class ModuleGetOutput : ModuleUpdateInput { }
2.5 新建模块分页输出 DTO 在 Output 目录下新建 ModuleGetPageOutput。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Output ;public class ModuleGetPageOutput { public long Id { get ; set ; } public string Name { get ; set ; } }
3. 新建模块服务接口 在以下目录中新建 Module 目录:
1 MyCompanyName.MyProjectName.Api\Services
然后在 Module 目录下新建模块服务类 ModuleService。
动态接口生成说明 若需要服务方法生成动态接口,需要在服务类上添加 [DynamicApi(Area = ApiConsts.AreaName)] 特性,并继承 IDynamicApi 接口。
提示:
使用项目模板开发时,请使用 AppRepositoryBase 基础仓储创建实体仓储。
在 Admin.Core 源码中开发时,请使用 AdminRepositoryBase 基础仓储创建实体仓储。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 using System.Threading.Tasks;using ZhonTai.Admin.Core.Dto;using ZhonTai.Admin.Services;using MyCompanyName.MyProjectName.Api.Contracts.Domain.Module;using MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;using MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Output;using MyCompanyName.MyProjectName.Api.Core.Consts;using ZhonTai;using ZhonTai.DynamicApi;using ZhonTai.DynamicApi.Attributes;using Microsoft.AspNetCore.Mvc;namespace MyCompanyName.MyProjectName.Api.Services.Module ;[DynamicApi(Area = ApiConsts.AreaName) ] public class ModuleService : BaseService , IDynamicApi { private readonly AppRepositoryBase<ModuleEntity> _moduleRep; public ModuleService (AppRepositoryBase<ModuleEntity> moduleRep ) { _moduleRep = moduleRep; } public async Task<ModuleGetOutput> GetAsync (long id ) { var result = await _moduleRep.GetAsync<ModuleGetOutput>(id); return result; } [HttpPost ] public async Task<PageOutput<ModuleGetPageOutput>> GetPageAsync(PageInput<ModuleGetPageInput> input) { var key = input.Filter?.Name; var list = await _moduleRep.Select .WhereIf(key.NotNull(), a => a.Name.Contains(key)) .Count(out var total) .OrderByDescending(true , c => c.Id) .Page(input.CurrentPage, input.PageSize) .ToListAsync<ModuleGetPageOutput>(); var data = new PageOutput<ModuleGetPageOutput> { List = list, Total = total }; return data; } public async Task<long > AddAsync (ModuleAddInput input ) { var entity = Mapper.Map<ModuleEntity>(input); await _moduleRep.InsertAsync(entity); return entity.Id; } public async Task UpdateAsync (ModuleUpdateInput input ) { var entity = await _moduleRep.GetAsync(input.Id); if (!(entity?.Id > 0 )) { throw ResultOutput.Exception("模块不存在" ); } Mapper.Map(input, entity); await _moduleRep.UpdateAsync(entity); } public async Task DeleteAsync (long id ) { await _moduleRep.DeleteAsync(m => m.Id == id); } public async Task SoftDeleteAsync (long id ) { await _moduleRep.SoftDeleteAsync(id); } public async Task BatchSoftDeleteAsync (long [] ids ) { await _moduleRep.SoftDeleteAsync(ids); } }
4. 接口权限说明 4.1 [Login] 使用 [Login] 标记接口时,表示该接口需要用户登录后才能访问。
该标记常用于测试未授权但需要登录的接口。
1 2 3 4 5 6 [Login ] public async Task<ModuleGetOutput> GetAsync (long id ){ var result = await _moduleRep.GetAsync<ModuleGetOutput>(id); return result; }
4.2 [AllowAnonymous] 使用 [AllowAnonymous] 标记接口时,表示该接口允许匿名访问。
该标记常用于测试未授权且未登录的接口。
1 2 3 4 5 6 [AllowAnonymous ] public async Task<ModuleGetOutput> GetAsync (long id ){ var result = await _moduleRep.GetAsync<ModuleGetOutput>(id); return result; }
5. 注意事项 授权接口需要删除以下标记:
否则可能会影响接口权限控制逻辑。
#中台 #中台/新建接口项目 #中台/.NET模板 #中台/搭建项目框架 #中台/数据库配置