Skip to content
Promote Your Product

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. Module can 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 with idx.

After inheriting EntityTenant, queries will filter data based on the TenantId.

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 ModuleService and inherit the IDynamicApi interface.

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.