π₯ Super, Sathish! Youβve completed Day 3 beautifully β now weβll move to
π
DAY 4 β Service + Controller Setup (User & Role API)
This is the day your project becomes alive β youβll be able to open Swagger and call /api/users to see data from PostgreSQL π
π― Goal
Connect database β repositories β services β controllers β Swagger test.
Weβll implement User + Role modules fully.
π§© Project Path Summary
| Layer | Folder | Purpose |
|---|---|---|
| Domain | Accounting.Domain/Entities |
Entity classes |
| Infrastructure | Accounting.Infrastructure/Repositories |
DB access |
| API |
Accounting.API/Controllers, Accounting.API/Services
|
Web API endpoints |
π§ DAY 4 Steps
Step 1 β Create Service Interfaces
π Accounting.API/Services/Interfaces/IUserService.cs
using Accounting.Core.Entities;
namespace Accounting.API.Services.Interfaces
{
public interface IUserService
{
Task<IEnumerable<User>> GetAllAsync();
Task<User?> GetByIdAsync(int id);
Task<User> CreateAsync(User user);
}
}
π Accounting.API/Services/Interfaces/IRoleService.cs
using Accounting.Core.Entities;
namespace Accounting.API.Services.Interfaces
{
public interface IRoleService
{
Task<IEnumerable<Role>> GetAllAsync();
}
}
Step 2 β Implement the Services
π Accounting.API/Services/Implementations/UserService.cs
using Accounting.Core.Entities;
using Accounting.Infrastructure.Repositories.Interfaces;
using Accounting.API.Services.Interfaces;
namespace Accounting.API.Services.Implementations
{
public class UserService : IUserService
{
private readonly IGenericRepository<User> _userRepo;
private readonly IUnitOfWork _uow;
public UserService(IGenericRepository<User> userRepo, IUnitOfWork uow)
{
_userRepo = userRepo;
_uow = uow;
}
public async Task<IEnumerable<User>> GetAllAsync() => await _userRepo.GetAllAsync();
public async Task<User?> GetByIdAsync(int id) => await _userRepo.GetByIdAsync(id);
public async Task<User> CreateAsync(User user)
{
await _userRepo.AddAsync(user);
await _uow.SaveChangesAsync();
return user;
}
}
}
π Accounting.API/Services/Implementations/RoleService.cs
using Accounting.Core.Entities;
using Accounting.Infrastructure.Repositories.Interfaces;
using Accounting.API.Services.Interfaces;
namespace Accounting.API.Services.Implementations
{
public class RoleService : IRoleService
{
private readonly IGenericRepository<Role> _roleRepo;
public RoleService(IGenericRepository<Role> roleRepo)
{
_roleRepo = roleRepo;
}
public async Task<IEnumerable<Role>> GetAllAsync() => await _roleRepo.GetAllAsync();
}
}
Step 3 β Register in Program.cs
π Accounting.API/Program.cs
using Accounting.Infrastructure.Repositories.Interfaces;
using Accounting.Infrastructure.Repositories.Implementations;
using Accounting.API.Services.Interfaces;
using Accounting.API.Services.Implementations;
using Accounting.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// PostgreSQL Connection
builder.Services.AddDbContext<AppDbContext>(opt =>
opt.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// Repository pattern
builder.Services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
// Services
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IRoleService, RoleService>();
// Swagger + CORS
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors(opt =>
{
opt.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
var app = builder.Build();
app.UseCors("AllowAll");
app.UseSwagger();
app.UseSwaggerUI();
app.MapControllers();
app.Run();
Step 4 β Create Controllers
π Accounting.API/Controllers/UserController.cs
using Accounting.API.Services.Interfaces;
using Accounting.Core.Entities;
using Microsoft.AspNetCore.Mvc;
namespace Accounting.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService) => _userService = userService;
[HttpGet]
public async Task<IActionResult> GetAll() =>
Ok(await _userService.GetAllAsync());
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var user = await _userService.GetByIdAsync(id);
return user == null ? NotFound() : Ok(user);
}
[HttpPost]
public async Task<IActionResult> Create(User user)
{
var created = await _userService.CreateAsync(user);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
}
}
}
π Accounting.API/Controllers/RoleController.cs
using Accounting.API.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace Accounting.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class RoleController : ControllerBase
{
private readonly IRoleService _roleService;
public RoleController(IRoleService roleService) => _roleService = roleService;
[HttpGet]
public async Task<IActionResult> GetAll() =>
Ok(await _roleService.GetAllAsync());
}
}
Step 5 β Run and Test
Run:
dotnet run
Open browser β https://localhost:5001/swagger
You should see endpoints:
GET /api/users
GET /api/users/{id}
POST /api/users
GET /api/roles
β Swagger returns your seeded Admin User and Admin Role.
β End of Day 4 Deliverables
| Feature | Status |
|---|---|
| User + Role Services | β |
| User + Role Controllers | β |
| Dependency Injection | β |
| Swagger working | β |
| Database Connected (PostgreSQL) | β |
Next β π
Day 5 β Invoice Module (Base Setup)
Weβll add Invoice, InvoiceItem, and Ledger logic with relationships, totals, and repositories.
Would you like me to prepare Day 5 plan (Invoice Module) now?
Top comments (0)