CleanCodeJN.GenericApis
1.1.0
See the version list below for details.
dotnet add package CleanCodeJN.GenericApis --version 1.1.0
NuGet\Install-Package CleanCodeJN.GenericApis -Version 1.1.0
<PackageReference Include="CleanCodeJN.GenericApis" Version="1.1.0" />
paket add CleanCodeJN.GenericApis --version 1.1.0
#r "nuget: CleanCodeJN.GenericApis, 1.1.0"
// Install CleanCodeJN.GenericApis as a Cake Addin #addin nuget:?package=CleanCodeJN.GenericApis&version=1.1.0 // Install CleanCodeJN.GenericApis as a Cake Tool #tool nuget:?package=CleanCodeJN.GenericApis&version=1.1.0
Generic Web Apis
CRUD support for WebAPIs with the power of Mediator pattern, Automapper, DataRepositories and Entity Framework
This CleanCodeJN package uses ready to use build-in Minimal API Extensions to have basic CRUD operations with the ability to customize complex business logic by the power of the the Integration/Operation Segregation Principle using Commands and Repository Patterns.
Features
- CRUD APIs (Minimal or Controller based) build in seconds
- Uses Mediator to abstract build-in and custom complex business logic
- Uses DataRepositories to abstract Entity Framework from business logic
- Enforces IOSP (Integration/Operation Segregation Principle) for commands
- Easy to mock and test
- On latest .NET 8.0
How to use
- Add RegisterRepositoriesCommandsWithAutomapper<IDataContext>() to your Program.cs
- Add app.RegisterApis() to your Program.cs or use AddControllers + MapControllers()
- Start writing Apis by implementing IApi
- Extend standard CRUD operations by specific Where() and Include() clauses
- Use IOSP for complex business logic
Step by step explanation
Add RegisterRepositoriesCommandsWithAutomapper<IDataContext>() to your Program.cs
builder.Services.RegisterRepositoriesCommandsWithAutomapper<MyDbContext>(cfg =>
{
cfg.CreateMap<Customer, CustomerPutDto>().ReverseMap();
cfg.CreateMap<Customer, CustomerPostDto>().ReverseMap();
cfg.CreateMap<Customer, CustomerGetDto>().ReverseMap();
});
Add app.RegisterApis() when using Minimal APIs to your Program.cs
app.RegisterApis();
When using Controllers add this to your Program.cs
builder.Services.AddControllers();
// After Build()
app.MapControllers();
Start writing Minimal Apis by implementing IApi
public class CustomersV1Api : IApi
{
public List<string> Tags => ["Customers V1"];
public string Route => $"api/v1/Customers";
public List<Func<WebApplication, RouteHandlerBuilder>> HttpMethods =>
[
app => app.MapGet<Customer, CustomerGetDto>(Route, Tags),
app => app.MapGetById<Customer, CustomerGetDto>(Route, Tags),
app => app.MapPut<Customer, CustomerPutDto, CustomerGetDto>(Route, Tags),
app => app.MapPost<Customer, CustomerPostDto, CustomerGetDto>(Route, Tags),
// Or use a custom Command with MapRequest
app => app.MapDeleteRequest(Route, Tags, async (int id, [FromServices] ApiBase api) =>
await api.Handle<Customer, CustomerGetDto>(new SpecificDeleteRequest { Id = id }))
];
}
Extend standard CRUD operations by specific Where() and Include() clauses
public class CustomersV1Api : IApi
{
public List<string> Tags => ["Customers V1"];
public string Route => $"api/v1/Customers";
public List<Func<WebApplication, RouteHandlerBuilder>> HttpMethods =>
[
app => app.MapGet<Customer, CustomerGetDto>(Route, Tags, where: x => x.Name.StartsWith("a")),
];
}
Or use ApiCrudControllerBase for CRUD operations in controllers
[Tags("Customers V3")]
[Route($"api/v3/[controller]")]
public class CustomersController(IMediator commandBus, IMapper mapper)
: ApiCrudControllerBase<Customer, CustomerGetDto, CustomerPostDto, CustomerPutDto>(commandBus, mapper)
{
}
You can also override your Where and Include clauses
[Tags("Customers V3")]
[Route($"api/v3/[controller]")]
public class CustomersController(IMediator commandBus, IMapper mapper)
: ApiCrudControllerBase<Customer, CustomerGetDto, CustomerPostDto, CustomerPutDto>(commandBus, mapper)
{
public override Expression<Func<Customer, bool>> GetWhere => x => x.Name.StartsWith("a");
public override List<Expression<Func<Customer, object>>> GetIncludes => [x => x.Invoices];
}
More Advanced Topics
Implement your own specific Request:
public class SpecificDeleteRequest : IRequest<BaseResponse<Customer>>
{
public required int Id { get; init; }
}
With your own specific Command using CleanCodeJN.Repository
public class SpecificDeleteCommand(IIntRepository<Customer> repository) : IRequestHandler<SpecificDeleteRequest, BaseResponse<Customer>>
{
public async Task<BaseResponse<Customer>> Handle(SpecificDeleteRequest request, CancellationToken cancellationToken)
{
var deletedCustomer = await repository.Delete(request.Id, cancellationToken);
return await BaseResponse<Customer>.Create(deletedCustomer is not null, deletedCustomer);
}
}
Use IOSP for complex business logic
Derive from BaseIntegrationCommand:
public class YourIntegrationCommand(ICommandExecutionContext executionContext)
: BaseIntegrationCommand(executionContext), IRequestHandler<YourIntegrationRequest, BaseResponse>
Write Extensions on ICommandExecutionContext with Built in Requests or with your own
public static ICommandExecutionContext CustomerGetByIdRequest(
this ICommandExecutionContext executionContext, int customerId)
=> executionContext.WithRequest(
() => new GetByIdRequest<Customer>
{
Id = customerId,
Includes = [x => x.Invoices, x => x.OtherDependentTable],
},
CommandConstants.CustomerGetById);
See the how clean your code will look like in the end
public class YourIntegrationCommand(ICommandExecutionContext executionContext)
: BaseIntegrationCommand(executionContext), IRequestHandler<YourIntegrationRequest, BaseResponse>
{
public async Task<BaseResponse> Handle(YourIntegrationRequest request, CancellationToken cancellationToken) =>
await ExecutionContext
.CandidateGetByIdRequest(request.Dto.CandidateId)
.CustomerGetByIdRequest(request.Dto.CustomerIds)
.GetOtherStuffRequest(request.Dto.XYZType)
.PostSomethingRequest(request.Dto)
.SendMailRequest()
.Execute(cancellationToken);
}
Sample Code
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- AutoMapper (>= 13.0.1)
- CleanCodeJN.Repository.EntityFramework (>= 1.1.1)
- MediatR (>= 12.2.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on CleanCodeJN.GenericApis:
Package | Downloads |
---|---|
CleanCodeJN.GenericApis.ServiceBusConsumer
This CleanCodeJN package for Service Bus simplifies the development of asynchronous microservices by providing a framework that leverages the power of MediatR and IOSP to consume service bus events from topics and execute commands to process these events. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.4.1 | 37 | 11/10/2024 |
3.4.0 | 36 | 11/10/2024 |
3.3.0 | 107 | 10/21/2024 |
3.2.2 | 104 | 10/20/2024 |
3.2.1 | 113 | 10/20/2024 |
3.2.0 | 104 | 10/20/2024 |
3.1.9 | 132 | 10/18/2024 |
3.1.8 | 91 | 10/9/2024 |
3.1.7 | 82 | 10/8/2024 |
3.1.6 | 88 | 10/8/2024 |
3.1.5 | 98 | 9/25/2024 |
3.1.4 | 117 | 9/12/2024 |
3.1.3 | 91 | 9/12/2024 |
3.1.2 | 93 | 9/12/2024 |
3.1.1 | 106 | 9/11/2024 |
3.1.0 | 90 | 9/9/2024 |
3.0.4 | 91 | 9/6/2024 |
3.0.3 | 95 | 9/6/2024 |
3.0.2 | 107 | 9/3/2024 |
3.0.1 | 73 | 7/30/2024 |
3.0.0 | 119 | 5/24/2024 |
2.2.0 | 100 | 5/23/2024 |
2.1.1 | 102 | 5/22/2024 |
2.1.0 | 105 | 5/15/2024 |
2.0.8 | 88 | 5/14/2024 |
2.0.7 | 99 | 5/14/2024 |
2.0.6 | 91 | 5/14/2024 |
2.0.5 | 94 | 5/13/2024 |
2.0.4 | 81 | 5/13/2024 |
2.0.3 | 86 | 5/12/2024 |
2.0.2 | 95 | 5/11/2024 |
2.0.1 | 96 | 5/8/2024 |
2.0.0 | 109 | 5/7/2024 |
1.1.1 | 108 | 5/7/2024 |
1.1.0 | 103 | 5/7/2024 |
1.0.6 | 122 | 5/7/2024 |
1.0.5 | 107 | 5/7/2024 |
1.0.4 | 108 | 5/7/2024 |
1.0.3 | 129 | 5/7/2024 |
1.0.2 | 105 | 5/6/2024 |
1.0.1 | 115 | 5/6/2024 |
1.0.0 | 114 | 5/6/2024 |
Also support for Controller based CRUD operations added.