
Create Module API (Repository)
1. Create Module Entity Class
Create a Module directory under MyCompanyName.MyProjectName.Api\Domain, and create an entity class ModuleEntity in the Module directory.
cs
using ZhonTai.Admin.Core.Entities;
using FreeSql.DataAnnotations;
using System;
namespace MyCompanyName.MyProjectName.Api.Domain.Module;
/// <summary>
/// Module
/// </summary>
[Table(Name = ApiConsts.AreaName + "_module")]
[Index("idx_{tablename}_01", nameof(TenantId) + "," + nameof(Name), true)]
public partial class ModuleEntity : EntityTenant
{
/// <summary>
/// Name
/// </summary>
[Column(StringLength = 50)]
public string Name { get; set; }
}Convention: Entity classes are suffixed with
Entity.Modulecan be replaced with the actual business module name. Table names and indexes use snake_case naming. Table name prefix starts with the app project prefix, and indexes start withidx.After inheriting
EntityTenant, queries will filter data based on theTenantId.
2. Create Module Repository Interface
Create a repository interface IModuleRepository under MyCompanyName.MyProjectName.Api\Domain\Module
cs
using ZhonTai.Admin.Core.Repositories;
namespace MyCompanyName.MyProjectName.Api.Domain.Module;
public interface IModuleRepository : IRepositoryBase<ModuleEntity>
{
}3. Create Module Repository
Create a Module directory under MyCompanyName.MyProjectName.Api\Repositories, and create a repository ModuleRepository implementing the IModuleRepository interface.
cs
using MyCompanyName.MyProjectName.Api.Core.Repositories;
using MyCompanyName.MyProjectName.Api.Domain.Module;
using ZhonTai.Admin.Core.Db.Transaction;
namespace MyCompanyName.MyProjectName.Api.Repositories;
public class ModuleRepository : AppRepositoryBase<ModuleEntity>, IModuleRepository
{
public ModuleRepository(UnitOfWorkManagerCloud uowm) : base(uowm)
{
}
}Note
The module repository must inherit from the App project's base repository AppRepositoryBase, using the current project's primary database to operate the module table.
4. Create Input/Output DTOs
Create Input or Output directories under MyCompanyName.MyProjectName.Api.Contracts\Services
Create the add input DTO ModuleAddInput in the Input directory:
cs
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;
/// <summary>
/// Add
/// </summary>
public class ModuleAddInput
{
/// <summary>
/// Name
/// </summary>
public string Name { get; set; }
}Create the update input DTO ModuleUpdateInput in the Input directory:
cs
using System.ComponentModel.DataAnnotations;
using ZhonTai.Admin.Core.Validators;
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;
/// <summary>
/// Update module
/// </summary>
public partial class ModuleUpdateInput : ModuleAddInput
{
/// <summary>
/// ID
/// </summary>
[Required]
[ValidateRequired("Please select a module")]
public long Id { get; set; }
}Create the page input DTO ModuleGetPageInput in the Input directory:
cs
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;
/// <summary>
/// Module page
/// </summary>
public partial class ModuleGetPageInput
{
/// <summary>
/// Name
/// </summary>
public string Name { get; set; }
}Create the query output DTO ModuleGetOutput in the Output directory:
cs
using MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;
namespace MyCompanyName.MyProjectName.Api.Services.Module.Output;
public class ModuleGetOutput : ModuleUpdateInput
{
}Create the page output DTO ModuleGetPageOutput in the Output directory:
cs
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Output;
/// <summary>
/// Module list
/// </summary>
public class ModuleGetPageOutput
{
/// <summary>
/// Primary key
/// </summary>
public long Id { get; set; }
/// <summary>
/// Name
/// </summary>
public string Name { get; set; }
}5. Create Module API
Create a Module directory under MyCompanyName.MyProjectName.Api\Services, and create a module service ModuleService in the Module directory.
How service methods generate dynamic APIs: Add the [DynamicApi(Area = ApiConsts.AreaName)] attribute to
ModuleServiceand inherit theIDynamicApiinterface.
cs
using System.Threading.Tasks;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services;
using MyCompanyName.MyProjectName.Api.Domain.Module;
using MyCompanyName.MyProjectName.Api.Domain.Module.Dto;
using MyCompanyName.MyProjectName.Api.Services.Module.Input;
using MyCompanyName.MyProjectName.Api.Services.Module.Output;
using MyCompanyName.MyProjectName.Api.Core.Consts;
using Newtonsoft.Json;
using ZhonTai;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using Microsoft.AspNetCore.Mvc;
using FreeScheduler;
namespace MyCompanyName.MyProjectName.Api.Services.Module;
/// <summary>
/// Module service
/// </summary>
[DynamicApi(Area = ApiConsts.AreaName)]
public class ModuleService : BaseService, IDynamicApi
{
private readonly IModuleRepository _moduleRepository;
public ModuleService(IModuleRepository moduleRepository)
{
_moduleRepository = moduleRepository;
}
/// <summary>
/// Get module
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRepository.GetAsync<ModuleGetOutput>(id);
return result;
}
/// <summary>
/// Get page
/// </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 _moduleRepository.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>
/// Add
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task<long> AddAsync(ModuleAddInput input)
{
var entity = Mapper.Map<ModuleEntity>(input);
await _moduleRepository.InsertAsync(entity);
return entity.Id;
}
/// <summary>
/// Update
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task UpdateAsync(ModuleUpdateInput input)
{
var entity = await _moduleRepository.GetAsync(input.Id);
if (!(entity?.Id > 0))
{
throw ResultOutput.Exception("Module does not exist");
}
Mapper.Map(input, entity);
await _moduleRepository.UpdateAsync(entity);
}
/// <summary>
/// Hard delete
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task DeleteAsync(long id)
{
await _moduleRepository.DeleteAsync(m => m.Id == id);
}
/// <summary>
/// Soft delete
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task SoftDeleteAsync(long id)
{
await _moduleRepository.SoftDeleteAsync(id);
}
/// <summary>
/// Batch soft delete
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _moduleRepository.SoftDeleteAsync(ids);
}
}API Permission Description
[Login]marks that the user must be logged in to access the API. This attribute is convenient for testing unauthorized APIs.
cs
[Login]
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRepository.GetAsync<ModuleGetOutput>(id);
return result;
}[AllowAnonymous]marks that the user can access the API anonymously. This attribute is convenient for testing APIs that are both unauthorized and unauthenticated.
cs
[AllowAnonymous]
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRepository.GetAsync<ModuleGetOutput>(id);
return result;
}Note
For authorized APIs, remove the [Login] and [AllowAnonymous] attributes.