DEV Community

Sugumar
Sugumar

Posted on

πŸ“… DAY 4 β€” Service + Controller Setup (User & Role API)

πŸ”₯ 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);
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“ Accounting.API/Services/Interfaces/IRoleService.cs

using Accounting.Core.Entities;

namespace Accounting.API.Services.Interfaces
{
    public interface IRoleService
    {
        Task<IEnumerable<Role>> GetAllAsync();
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“ 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();
    }
}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“ 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());
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 5 – Run and Test

Run:

dotnet run
Enter fullscreen mode Exit fullscreen mode

Open browser β†’ https://localhost:5001/swagger

You should see endpoints:

GET  /api/users
GET  /api/users/{id}
POST /api/users
GET  /api/roles
Enter fullscreen mode Exit fullscreen mode

βœ… 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)