Introduction
ShopNest's Product Catalog API exposes products to mobile apps and partners using REST — resources identified by URLs, manipulated with HTTP verbs, and described with proper status codes and DTOs (never raw EF entities).
After this article you will
- Apply REST principles and resource-oriented URLs
- Use [ApiController] and attribute routing
- Return correct status codes with ActionResult<T>
- Separate request/response DTOs from domain models
- Build full product CRUD API testable in Postman
Prerequisites
- Article 35 — HTTPS, SSL Certificates and Security
- ShopNest with EF Core and auth from Modules 2–4
Concept deep-dive
| Method | Action | Success code |
|---|---|---|
| GET | List / get by id | 200 |
| POST | Create | 201 + Location header |
| PUT | Full replace | 200 / 204 |
| PATCH | Partial update | 200 |
| DELETE | Remove | 204 |
[ApiController]
[Route("api/v1/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public async Task<ActionResult<IEnumerable<ProductListDto>>> GetAll()
=> Ok(await _service.GetAllAsync());
[HttpGet("{id:int}")]
public async Task<ActionResult<ProductDetailDto>> Get(int id)
{
var p = await _service.GetByIdAsync(id);
return p == null ? NotFound() : Ok(p);
}
[HttpPost]
public async Task<ActionResult<ProductDetailDto>> Create(CreateProductDto dto)
{
var created = await _service.CreateAsync(dto);
return CreatedAtAction(nameof(Get), new { id = created.Id }, created);
}
}
[ApiController] enables automatic 400 on invalid model, binding source inference, and ProblemDetails for errors.
Postman example: POST /api/v1/products body {"name":"Keyboard","price":2499} → 201 Created with Location: .../products/42.
Hands-on — ShopNest Product Catalog API
- Create ShopNest.Api project; reference Application + Infrastructure.
- ProductListDto, ProductDetailDto, CreateProductDto.
- ProductsController full CRUD + JWT [Authorize] from Article 32.
- Postman collection: GET list, GET by id, POST, PUT, DELETE.
Common errors & best practices
- Returning entity with navigation properties — circular JSON and data leaks.
- 200 on POST create — use 201 CreatedAtAction.
- GET returning IEnumerable without pagination — Article 40 fixes this.
Interview questions
Q: IActionResult vs ActionResult<T>?
A: ActionResult<T> documents response type for OpenAPI; still allows NotFound() etc.
Q: What does [ApiController] do?
A: Automatic model validation 400, attribute routing assumptions, ProblemDetails.
Q: REST vs RPC?
A: REST uses nouns (resources) + HTTP verbs; RPC uses action URLs like /calculateTax.
Summary
- REST = resources + HTTP verbs + meaningful status codes
- DTOs protect domain and shape API contracts
- ApiController + CreatedAtAction for professional CRUD
- Product Catalog API is ShopNest mobile backbone
Previous: HTTPS, SSL Certificates and Security
Next: API Versioning
FAQ
XML responses?
Add XmlSerializerFormatters — JSON is default for modern clients.
Controller vs Minimal API?
Both valid — Article 42 compares; controllers better for large teams initially.