May 26 2025
dotnet add package Carter dotnet add package FluentValidation dotnet add package FluentValidation.DependencyInjectionExtensions
var builder = WebApplication.CreateBuilder(args); builder.Services.AddCarter(); builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddValidatorsFromAssemblyContaining<CreateUserValidator>(); var app = builder.Build(); app.MapCarter(); app.Run();
public class User { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; } public record CreateUserRequest(string Name, string Email);
// Validators/CreateUserValidator.cs using FluentValidation; public class CreateUserValidator : AbstractValidator<CreateUserRequest> { public CreateUserValidator() { RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required"); RuleFor(x => x.Email).EmailAddress().WithMessage("Invalid email format"); } }
public interface IUserService { IEnumerable<User> GetAllUsers(); User? GetUserById(int id); User CreateUser(CreateUserRequest request); }
public class UserService : IUserService { private readonly List<User> _users = [ new User { Id = 1, Name = "Alice", Email = "alice@example.com" }, new User { Id = 2, Name = "Bob", Email = "bob@example.com" } ]; public List<User> GetAllUsers() { return _users; } public User? GetUserById(int id) { return _users.FirstOrDefault(u => u.Id == id); } public User CreateUser(CreateUserRequest request) { var user = new User { Id = _users.Max(u => u.Id) + 1, Name = request.Name, Email = request.Email }; _users.Add(user); return user; } }
public class UserModule : ICarterModule { public void AddRoutes(IEndpointRouteBuilder app) { app.MapGet("/users", (IUserService userService) => { var users = userService.GetAllUsers(); return Results.Ok(users); }); app.MapGet("/users/{id:int}", (int id, IUserService userService) => { var user = userService.GetUserById(id); return user is null ? Results.NotFound("User not found") : Results.Ok(user); }); app.MapPost("/users", async ( HttpRequest req, IUserService userService, IValidator<CreateUserRequest> validator) => { var userRequest = await req.ReadFromJsonAsync<CreateUserRequest>(); if (userRequest is null) return Results.BadRequest("Invalid request payload"); ValidationResult validationResult = await validator.ValidateAsync(userRequest); if (!validationResult.IsValid) return Results.BadRequest(validationResult.Errors); var newUser = userService.CreateUser(userRequest); return Results.Created($"/users/{newUser.Id}", newUser); }); } }
var group = app.MapGroup("/users"); group.MapGet("/", (IUserService service) => Results.Ok(service.GetAllUsers())); group.MapGet("/{id:int}", (int id, IUserService service) => { var user = service.GetUserById(id); return user is null ? Results.NotFound() : Results.Ok(user); });
public UserModule() : base("/api") // All endpoints will be prefixed with /api { WithTags("Users"); // Swagger/OpenAPI tag for this module IncludeInOpenApi(); // Automatically include all endpoints in Swagger }
1. Design Patterns that Deliver
This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.
Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.
Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.
Join 18,000+ subscribers to improve your .NET Knowledge.
Subscribe to the TheCodeMan.net and be among the 18,000+ subscribers gaining practical tips and resources to enhance your .NET expertise.