From ABP Sensei
Guides through ABP Framework v10.4 end-to-end flow for adding a new entity/feature: Domain, EF Core config/migration, DTOs, app service, localization, permissions, tests.
How this skill is triggered — by the user, by Claude, or both
Slash command
/abp-sensei:abp-development-flowThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The flow for adding a new entity/feature **end-to-end** in ABP Framework v10.4 (layered template). Proceed across layers in the correct order.
The flow for adding a new entity/feature end-to-end in ABP Framework v10.4 (layered template). Proceed across layers in the correct order.
*.Domain/Entities/)public class Book : AggregateRoot<Guid>
{
public string Name { get; private set; }
public decimal Price { get; private set; }
public Guid AuthorId { get; private set; }
protected Book() { }
public Book(Guid id, string name, decimal price, Guid authorId) : base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
SetPrice(price);
AuthorId = authorId;
}
public void SetPrice(decimal price) => Price = Check.Range(price, nameof(price), 0, 9999);
}
*.Domain.Shared/)public static class BookConsts { public const int MaxNameLength = 128; }
public enum BookType { Novel, Science, Biography }
*.Domain/)public interface IBookRepository : IRepository<Book, Guid>
{
Task<Book> FindByNameAsync(string name);
}
For simple CRUD, IRepository<Book, Guid> is sufficient.
*.EntityFrameworkCore/)// DbContext
public DbSet<Book> Books { get; set; }
// OnModelCreating
builder.Entity<Book>(b =>
{
b.ToTable(MyProjectConsts.DbTablePrefix + "Books", MyProjectConsts.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.Name).IsRequired().HasMaxLength(BookConsts.MaxNameLength);
b.HasIndex(x => x.Name);
});
cd src/MyProject.EntityFrameworkCore
dotnet ef migrations add Added_Book
dotnet run --project ../MyProject.DbMigrator # Recommended — also runs seed data
public class BookDto : EntityDto<Guid> { public string Name { get; set; } public decimal Price { get; set; } }
public class CreateBookDto
{
[Required, StringLength(BookConsts.MaxNameLength)] public string Name { get; set; }
[Range(0, 9999)] public decimal Price { get; set; }
[Required] public Guid AuthorId { get; set; }
}
public interface IBookAppService : IApplicationService
{
Task<BookDto> GetAsync(Guid id);
Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input);
Task<BookDto> CreateAsync(CreateBookDto input);
}
[Mapper]
public partial class BookMapper : MapperBase<Book, BookDto>
{
public override partial BookDto Map(Book source);
public override partial void Map(Book source, BookDto destination);
}
Detail: Object Mapping skill.
public class BookAppService : ApplicationService, IBookAppService
{
private readonly IRepository<Book, Guid> _bookRepository; // or IBookRepository
public BookAppService(IRepository<Book, Guid> bookRepository) => _bookRepository = bookRepository;
public async Task<BookDto> GetAsync(Guid id)
=> ObjectMapper.Map<Book, BookDto>(await _bookRepository.GetAsync(id));
[Authorize(MyProjectPermissions.Books.Create)]
public async Task<BookDto> CreateAsync(CreateBookDto input)
{
var book = new Book(GuidGenerator.Create(), input.Name, input.Price, input.AuthorId);
await _bookRepository.InsertAsync(book);
return ObjectMapper.Map<Book, BookDto>(book);
}
}
*.Domain.Shared/Localization/*/en.json){ "Book": "Book", "Books": "Books", "BookName": "Name", "BookPrice": "Price" }
*.Application.Contracts/)public static class MyProjectPermissions
{
public static class Books
{
public const string Default = "MyProject.Books";
public const string Create = Default + ".Create";
}
}
public class BookAppService_Tests : MyProjectApplicationTestBase
{
private readonly IBookAppService _bookAppService;
public BookAppService_Tests() => _bookAppService = GetRequiredService<IBookAppService>();
[Fact]
public async Task Should_Create_Book()
{
var result = await _bookAppService.CreateAsync(new CreateBookDto { Name = "Test", Price = 19.99m });
result.Id.ShouldNotBe(Guid.Empty);
}
}
Detail: Testing skill.
dotnet build
cd src/MyProject.EntityFrameworkCore && dotnet ef migrations add MigrationName
dotnet run --project ../MyProject.DbMigrator # apply migration + seed
abp generate-proxy -t ng # Angular proxy
ConfigureByConvention()npx claudepluginhub burakdmir/abp-skills --plugin abp-senseiProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.