KSFramework is a modular and extensible .NET framework that simplifies the implementation of enterprise-grade applications using Clean Architecture, DDD, and CQRS patterns. It includes built-in support for Generic Repository, Unit of Work, and a custom MediatR-style messaging system, some useful extension methods, helpers, common Enums, Common Exceptions, Unified API Result, Common Specifications, Pagination Helper, Common Responses, .NET Core Tag Helpers and some Utilities.
- ✅ Clean Architecture and DDD-friendly structure
- ✅ Generic Repository with constraint on AggregateRoots
- ✅ Fully extensible Unit of Work pattern
- ✅ Built-in Pagination utilities
- ✅ Internal MediatR-like message dispatch system (KSMessaging)
- ✅ Scrutor-based handler and behavior registration
- ✅ Support for pipeline behaviors (logging, validation, etc.)
- ✅ Strongly testable, loosely coupled abstractions
Install via NuGet:
dotnet add package KSFrameworkKSFramework.KSDomain— Domain primitives:Entity,AggregateRoot,ValueObjectKSFramework.GenericRepository—Repository,UnitOfWork, pagination supportKSFramework.KSMessaging— CQRS with internal MediatR-style handler resolver, behaviors, stream handlingKSFramework.Enums- Common EnumsKSFramework.Exceptions- Common ExceptionsKSFramework.KSApi- Unified API ResultKSFramework.Pagination- Pagination HelperKSFramework.Responses- Common ResponsesKSFramework.TagHelpers- .NET Core Tag HelpersKSFramework.Utilities- Common Utiliti Extension Methods
builder.Services.AddKSMediator(typeof(Program).Assembly); // Pass the assembly (array of assemblies) that your MediatR Handlers located in, like Application Project
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();public record CreatePostCommand(string Title, string Content) : ICommand<Guid>;
public class CreatePostHandler : ICommandHandler<CreatePostCommand, Guid>
{
private readonly IUnitOfWork _uow;
public CreatePostHandler(IUnitOfWork uow)
{
_uow = uow;
}
public async Task<Guid> Handle(CreatePostCommand request, CancellationToken cancellationToken)
{
var post = new BlogPost { Id = Guid.NewGuid(), Title = request.Title, Content = request.Content };
await _uow.GetRepository<BlogPost>().AddAsync(post);
await _uow.SaveChangesAsync();
return post.Id;
}
}- CRUD for Blog Posts using Commands/Queries
- Subscriber registration using Notification pattern
- Weekly newsletter dispatch via background service
public class BlogPost : AggregateRoot<Guid>
{
public string Title { get; set; }
public string Content { get; set; }
public DateTime PublishedAt { get; set; }
}
public class Subscriber : Entity<Guid>
{
public string Email { get; set; }
}public record SubscribeCommand(string Email) : ICommand;
public class SubscribeHandler : ICommandHandler<SubscribeCommand>
{
private readonly IUnitOfWork _uow;
public SubscribeHandler(IUnitOfWork uow) => _uow = uow;
public async Task Handle(SubscribeCommand request, CancellationToken cancellationToken)
{
var repo = _uow.GetRepository<Subscriber>();
await repo.AddAsync(new Subscriber { Email = request.Email });
await _uow.SaveChangesAsync();
}
}[ApiController]
[Route("api/[controller]")]
public class NewsletterController : ControllerBase
{
private readonly ISender _sender;
public NewsletterController(ISender sender) => _sender = sender;
[HttpPost("subscribe")]
public async Task<IActionResult> Subscribe([FromForm] string email)
{
await _sender.Send(new SubscribeCommand(email));
return Ok("Subscribed");
}
}public class WeeklyNewsletterJob
{
private readonly IUnitOfWork _uow;
public WeeklyNewsletterJob(IUnitOfWork uow) => _uow = uow;
public async Task SendAsync()
{
var posts = (await _uow.GetRepository<BlogPost>().GetAllAsync())
.Where(p => p.PublishedAt >= DateTime.UtcNow.AddDays(-7));
var subscribers = await _uow.GetRepository<Subscriber>().GetAllAsync();
foreach (var s in subscribers)
{
await EmailSender.Send(s.Email, "Your Weekly Digest", string.Join("\n", posts.Select(p => p.Title)));
}
}
}- Handlers and pipelines are fully testable using unit tests
- Use
KSFramework.UnitTestsproject to validate handler behavior - Custom behaviors can be tested independently
- Implement changes
- Add and Commit changes in git
- Tag the changes
git tag vX.Y.Z - Push the changes
git push - Create Pull Request and merge changes
- Push the tag
git push origin vX.Y.Z
Licensed under MIT.