Series: From Code to Cloud: Building a Production-Ready .NET Application
By: Farrukh Rehman - Senior .NET Full Stack Developer / Team Lead
LinkedIn: https://linkedin.com/in/farrukh-rehman
GitHub: https://github.com/farrukh1212cs
Source Code Backend : https://github.com/farrukh1212cs/ECommerce-Backend.git
Source Code Frontend : https://github.com/farrukh1212cs/ECommerce-Frontend.git
Introduction
In this lecture, we’ll build API Controllers for each major entity.
Each controller will:
- Use dependency injection to call the respective service.
- Handle CRUD operations (GET, POST, PUT, DELETE).
- Return DTOs instead of domain entities.
- Follow Clean Architecture — meaning no direct data access here.
We’ll also make sure to use standard conventions:
- api/[controller] routes
- ActionResult return types
- IActionResult for operations
File Structure
Creating First Controller
Product Controller
Path: ECommerce.API/Controllers/ProductsController.cs
using ECommerce.Application.DTOs;
using ECommerce.Application.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ECommerce.API.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<ProductDto>>> GetAll()
{
var products = await _productService.GetAllAsync();
return Ok(products);
}
[HttpGet("{id}")]
public async Task<ActionResult<ProductDto>> GetById(Guid id)
{
var product = await _productService.GetByIdAsync(id);
if (product == null)
return NotFound();
return Ok(product);
}
[HttpPost]
public async Task<ActionResult> Create(ProductDto dto)
{
await _productService.AddAsync(dto);
return CreatedAtAction(nameof(GetById), new { id = dto.Id }, dto);
}
[HttpPut("{id}")]
public async Task<ActionResult> Update(Guid id, ProductDto dto)
{
if (id != dto.Id)
return BadRequest("Mismatched product ID.");
await _productService.UpdateAsync(dto);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<ActionResult> Delete(Guid id)
{
await _productService.DeleteAsync(id);
return NoContent();
}
}
Customer Controller
using ECommerce.Application.DTOs;
using ECommerce.Application.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ECommerce.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
private readonly ICustomerService _customerService;
public CustomersController(ICustomerService customerService)
{
_customerService = customerService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<CustomerDto>>> GetAll()
{
return Ok(await _customerService.GetAllAsync());
}
[HttpGet("{id}")]
public async Task<ActionResult<CustomerDto>> GetById(Guid id)
{
var customer = await _customerService.GetByIdAsync(id);
if (customer == null)
return NotFound();
return Ok(customer);
}
[HttpPost]
public async Task<ActionResult> Create(CustomerDto dto)
{
await _customerService.AddAsync(dto);
return CreatedAtAction(nameof(GetById), new { id = dto.Id }, dto);
}
[HttpPut("{id}")]
public async Task<ActionResult> Update(Guid id, CustomerDto dto)
{
if (id != dto.Id)
return BadRequest();
await _customerService.UpdateAsync(dto);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<ActionResult> Delete(Guid id)
{
await _customerService.DeleteAsync(id);
return NoContent();
}
}
}
Order Controller
using ECommerce.Application.DTOs;
using ECommerce.Application.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ECommerce.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IOrderService _orderService;
public OrdersController(IOrderService orderService)
{
_orderService = orderService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<OrderDto>>> GetAll()
{
return Ok(await _orderService.GetAllAsync());
}
[HttpGet("{id}")]
public async Task<ActionResult<OrderDto>> GetById(Guid id)
{
var order = await _orderService.GetByIdAsync(id);
if (order == null)
return NotFound();
return Ok(order);
}
[HttpPost]
public async Task<ActionResult> Create(OrderDto dto)
{
await _orderService.AddAsync(dto);
return CreatedAtAction(nameof(GetById), new { id = dto.Id }, dto);
}
[HttpPut("{id}")]
public async Task<ActionResult> Update(Guid id, OrderDto dto)
{
if (id != dto.Id)
return BadRequest();
await _orderService.UpdateAsync(dto);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<ActionResult> Delete(Guid id)
{
await _orderService.DeleteAsync(id);
return NoContent();
}
}
}
Order Item Controller
using ECommerce.Application.DTOs;
using ECommerce.Application.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ECommerce.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class OrderItemsController : ControllerBase
{
private readonly IOrderItemService _orderItemService;
public OrderItemsController(IOrderItemService orderItemService)
{
_orderItemService = orderItemService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<OrderItemDto>>> GetAll()
{
return Ok(await _orderItemService.GetAllAsync());
}
[HttpGet("by-order/{orderId}")]
public async Task<ActionResult<IEnumerable<OrderItemDto>>> GetByOrderId(Guid orderId)
{
var items = await _orderItemService.GetByOrderIdAsync(orderId);
return Ok(items);
}
}
}
Next Lecture Preview
Lecture 3 : Integrating MySQL (First Database)
Setting up MySQL, creating initial migrations, and implementing CRUD operations for base entities.






Top comments (0)