Overview
The API layer in Clean.Net is designed to be lightweight and serves purely as an entry point to the application. This design follows Clean Architecture principles, ensuring:
- Clear separation of concerns - API layer only handles HTTP requests/responses
- Easy interface replacement - API layer can be swapped with minimal impact
- Isolated business logic - All business rules reside in the Application layer
- One-to-one mapping - Each endpoint corresponds to a single handler (CQRS pattern) in the appllication layer
Adding a New Endpoint
Example based on User management:
1. Controller Endpoint
// API Layer
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IMediator _mediator;
public UserController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost()]
[Authorize(Policy = AuthorisationPolicyNames.RequireAdmin)]
[ProducesResponseType(typeof(CreateUserResponse), 201)]
[ProducesResponseType(typeof(ProblemDetails<CreateUserError>), 400)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> CreateUser(CreateUserRequest request, CancellationToken cancellationToken) =>
await _mediator.SendWithErrorHandling<CreateUserResponse, CreateUserError>(request, cancellationToken);
}
3. Handler Implementation
// Application Layer
public class CreateUserHandler : IRequestHandler<CreateUserRequest, Result<CreateUserResponse>>
{
private readonly IUserRepository _userRepository;
private readonly IPasswordHasher<Domain.Entities.User> _passwordHasher;
public CreateUserHandler(IUserRepository userRepository, IPasswordHasher<Domain.Entities.User> passwordHasher)
{
_userRepository = userRepository;
_passwordHasher = passwordHasher;
}
public async Task<Result<CreateUserResponse>> Handle(CreateUserRequest request, CancellationToken cancellationToken)
{
var user = await _userRepository.Get(request.Id);
if (user is null)
{
var hashedPassword = _passwordHasher.HashPassword(null!, request.Password);
user = request.ToUser(hashedPassword);
await _userRepository.Add(user);
}
return user.ToCreateUserResponse();
}
}
All endpoints are made available on the Swagger UI
page. Visit API Documentation page for more details