Admin Core

新建模块接口

本文以 Module 模块为例,说明如何新建模块实体类、输入输出 DTO 以及模块服务接口。

本文以 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;

/// <summary>
/// 模块
/// </summary>
[Table(Name = DbConsts.TableNamePrefix + "module")]
[Index("idx_{tablename}_01", nameof(TenantId) + "," + nameof(Name), true)]
public partial class ModuleEntity : EntityTenant
{
/// <summary>
/// 名称
/// </summary>
[Column(StringLength = 50)]
public string Name { get; set; }
}

约定说明

  • 实体类以 Entity 结尾,例如:ModuleEntity
  • 表名和索引采用下划线命名法。
  • 表名前缀统一使用 DbConsts.TableNamePrefix
  • 索引名称以 idx 开头。
  • 继承 EntityTenant 后,查询数据时会自动根据租户编号 TenantId 进行数据筛选。

2. 新建输入输出 DTO

在以下目录下新建 InputOutput 目录:

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;

/// <summary>
/// 添加模块
/// </summary>
public class ModuleAddInput
{
/// <summary>
/// 名称
/// </summary>
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;

/// <summary>
/// 修改模块
/// </summary>
public partial class ModuleUpdateInput : ModuleAddInput
{
/// <summary>
/// 编号
/// </summary>
[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;

/// <summary>
/// 模块分页请求
/// </summary>
public partial class ModuleGetPageInput
{
/// <summary>
/// 名称
/// </summary>
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;

/// <summary>
/// 模块详情响应
/// </summary>
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;

/// <summary>
/// 模块分页响应
/// </summary>
public class ModuleGetPageOutput
{
/// <summary>
/// 主键
/// </summary>
public long Id { get; set; }

/// <summary>
/// 名称
/// </summary>
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;

/// <summary>
/// 模块服务
/// </summary>
[DynamicApi(Area = ApiConsts.AreaName)]
public class ModuleService : BaseService, IDynamicApi
{
private readonly AppRepositoryBase<ModuleEntity> _moduleRep;

public ModuleService(AppRepositoryBase<ModuleEntity> moduleRep)
{
_moduleRep = moduleRep;
}

/// <summary>
/// 查询模块
/// </summary>
/// <param name="id">模块编号</param>
/// <returns>模块详情</returns>
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRep.GetAsync<ModuleGetOutput>(id);
return result;
}

/// <summary>
/// 查询分页
/// </summary>
/// <param name="input">分页查询参数</param>
/// <returns>模块分页列表</returns>
[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;
}

/// <summary>
/// 新增模块
/// </summary>
/// <param name="input">新增参数</param>
/// <returns>模块编号</returns>
public async Task<long> AddAsync(ModuleAddInput input)
{
var entity = Mapper.Map<ModuleEntity>(input);
await _moduleRep.InsertAsync(entity);

return entity.Id;
}

/// <summary>
/// 修改模块
/// </summary>
/// <param name="input">修改参数</param>
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);
}

/// <summary>
/// 彻底删除模块
/// </summary>
/// <param name="id">模块编号</param>
public async Task DeleteAsync(long id)
{
await _moduleRep.DeleteAsync(m => m.Id == id);
}

/// <summary>
/// 软删除模块
/// </summary>
/// <param name="id">模块编号</param>
public async Task SoftDeleteAsync(long id)
{
await _moduleRep.SoftDeleteAsync(id);
}

/// <summary>
/// 批量软删除模块
/// </summary>
/// <param name="ids">模块编号集合</param>
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. 注意事项

授权接口需要删除以下标记:

  • [Login]
  • [AllowAnonymous]

否则可能会影响接口权限控制逻辑。

#中台 #中台/新建接口项目 #中台/.NET模板 #中台/搭建项目框架 #中台/数据库配置