Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
6237a4f
Initial project commit
JJHH17 Sep 28, 2025
187d5c9
Installed entity framework packages
JJHH17 Sep 28, 2025
c4f807b
Added dbContext
JJHH17 Sep 28, 2025
e2ab51e
Added connection string to localDb SqlServer instance
JJHH17 Sep 28, 2025
83ee73c
Added reference to connection string
JJHH17 Sep 28, 2025
67f56b0
Added reference to product model
JJHH17 Sep 28, 2025
86e669d
Created initial product model
JJHH17 Sep 28, 2025
e5cd1c0
Added required tags to product variables
JJHH17 Sep 28, 2025
d6dfc0a
Resolved typo in connection string
JJHH17 Sep 28, 2025
9d1a617
Added reference to productService
JJHH17 Sep 28, 2025
21f7056
Created product service methods
JJHH17 Sep 28, 2025
36e2f38
Created products controller file
JJHH17 Sep 29, 2025
960eae8
Added basic 'not found' errors to controller
JJHH17 Sep 29, 2025
d10cdbb
Added basic 'not found' errors to controller
JJHH17 Sep 29, 2025
83633da
Created endpoints for Products
JJHH17 Sep 30, 2025
a9010d2
Created db context for products
JJHH17 Sep 30, 2025
2f17a78
Refactored products class, pre category introductions
JJHH17 Sep 30, 2025
4ca62e7
Created base products service
JJHH17 Sep 30, 2025
33f27d0
Resolved typo in Get header, bug due to mistyped bracket
JJHH17 Sep 30, 2025
1906d21
Created products relationship with categories
JJHH17 Sep 30, 2025
9c6ea8b
Created model for product which feeds to categories
JJHH17 Sep 30, 2025
9d25885
Created category model
JJHH17 Sep 30, 2025
b10df84
Created categories controller class
JJHH17 Oct 1, 2025
cc565fd
Created categories service
JJHH17 Oct 1, 2025
32f5b8f
Created a dto which allows users to create category
JJHH17 Oct 1, 2025
65226b6
Added support for category creation dto
JJHH17 Oct 1, 2025
59fe6a7
Added create category dto support
JJHH17 Oct 1, 2025
a0f5e64
Added category creation support via API, now supports those endpoints
JJHH17 Oct 1, 2025
98f1e19
Amended products controller which now references the Category ID
JJHH17 Oct 2, 2025
634aa74
Amended product DTO for creation to reference category by ID
JJHH17 Oct 2, 2025
8db809b
Amended createProduct call to take in the category ID
JJHH17 Oct 2, 2025
736ccc6
GetAllProducts method now returns a DTO list
JJHH17 Oct 2, 2025
9c1113c
Created a DTO for fetching a list of products
JJHH17 Oct 2, 2025
df39166
We now return a list of products based on the DTO model
JJHH17 Oct 2, 2025
97483f3
Created dto helper for displaying categories for GET request
JJHH17 Oct 2, 2025
855fbf3
Added support for getAllCategories method
JJHH17 Oct 2, 2025
f577e56
Added product creator dto
JJHH17 Oct 2, 2025
287cab7
Altered createProduct method which now returns the name of the catego…
JJHH17 Oct 2, 2025
e999b0d
Removed delete and update requests for products
JJHH17 Oct 2, 2025
666c1f0
Removed delete and update calls
JJHH17 Oct 2, 2025
090df33
Enhanced method to fetch categories based on ID
JJHH17 Oct 2, 2025
5ac3221
Enhanced get product by ID response
JJHH17 Oct 2, 2025
27e7581
Created Sale model
JJHH17 Oct 3, 2025
e7dedff
Added reference to sales model
JJHH17 Oct 3, 2025
ce681f1
Added sales to product many to many modelBuilder
JJHH17 Oct 3, 2025
3225fd6
Added reference to sales table
JJHH17 Oct 3, 2025
11a2e69
Created many to many sales model
JJHH17 Oct 3, 2025
f008877
Added inclusion of sales table
JJHH17 Oct 3, 2025
11ee02c
Created sales controller for API calls
JJHH17 Oct 3, 2025
5e20934
Created sales service class
JJHH17 Oct 3, 2025
ad868eb
Added singleorDefault method, preventing an errored response if ID is…
JJHH17 Oct 6, 2025
60712e1
Added try catch area for adding sales
JJHH17 Oct 6, 2025
10bfd34
Added postman collection
JJHH17 Oct 6, 2025
2d506ee
Created paged response model
JJHH17 Oct 6, 2025
01360db
Added initial response pagination model
JJHH17 Oct 6, 2025
ba8f483
Added pagination model
JJHH17 Oct 6, 2025
315fb77
Added pagination for the GetAllProducts endpoint
JJHH17 Oct 7, 2025
d9282c9
Added pagination model
JJHH17 Oct 7, 2025
5080b8b
Added data seeding for products and categories
JJHH17 Oct 7, 2025
4daf0b8
Added initial migrations
JJHH17 Oct 7, 2025
0a3abb4
Removed unread using string
JJHH17 Oct 7, 2025
6d246d4
removed unused using strings
JJHH17 Oct 7, 2025
2006e78
Create README.md
JJHH17 Oct 8, 2025
205a710
Update README.md
JJHH17 Oct 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using ECommerceApi.JJHH17.Models;
using ECommerceApi.JJHH17.Services;
using Microsoft.AspNetCore.Mvc;

namespace ECommerceApi.JJHH17.Controllers
{
Comment on lines +5 to +6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Namespaces

💡 As per the academy's code-conventions, use file-scoped namespaces.

➡️ From C# 10, we are able to remove the block/braces and save on level of indentation, optimising space and improving readability.

Suggested change
namespace ECommerceApi.JJHH17.Controllers
{
namespace ECommerceApi.JJHH17.Controllers;

[ApiController]
[Route("api/[controller]")]
// Example call: http://localhost:5609/api/category/
public class CategoriesController : ControllerBase
{
private readonly ICategoryService _categoryService;

public CategoriesController(ICategoryService categoryService)
{
_categoryService = categoryService;
}

[HttpGet]
public ActionResult<PagedResponse<CategoryWithProductsDto>> GetAllCategories([FromQuery] Pagination pagination)
{
if (pagination.PageNumber < 1) pagination.PageNumber = 1;
if (pagination.PageSize < 1) pagination.PageSize = 10;

var allCategories = _categoryService.GetAllCategories();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Inefficient

💡 Great job implementing pagination. But ideally you would want to pass the pagination responsibility down to your db context.

💭 Say your database has 10m rows. Currently your api would get 10m rows from the database, hold in memory and then filter down to the first 10 rows (as an example). Imagine the cost, time, and resource implications of this. If using a cloud database provider you would quickly run out of money.

🔧 Instead you should use the database to only get the 10 rows you need, only hold 10 rows in memory, etc, etc.


var totalRecords = allCategories.Count;
var pagedData = allCategories
.OrderBy(c => c.CategoryId)
.Skip((pagination.PageNumber - 1) * pagination.PageSize)
.Take(pagination.PageSize)
.ToList();

return Ok(pagedData);
}

[HttpGet("{id}")]
public ActionResult<Category> GetCategoryById(int id)
{
var result = _categoryService.GetCategoryById(id);

if (result == null) { return NotFound(); }

return Ok(result);
Comment on lines +42 to +44

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Simplify

💡 Use the ternary conditional operator. condition ? consequent : alternative

💭 e.g. IfThisIsTrue ? DoThis : ElseDoThis

Suggested change
if (result == null) { return NotFound(); }
return Ok(result);
return result is null
? NotFound()
: Ok(result);

}

[HttpPost]
public ActionResult<CreateCategoryDto> CreateCategory(CreateCategoryDto category)
{
return Ok(_categoryService.CreateCategory(category));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 REST

💡 Post requests should return a 201 Created response to indicate successful creation and the location of the created resource.

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using ECommerceApi.JJHH17.Models;
using ECommerceApi.JJHH17.Services;
using Microsoft.AspNetCore.Mvc;

namespace ECommerceApi.JJHH17.Controllers
{
Comment on lines +5 to +6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
namespace ECommerceApi.JJHH17.Controllers
{
namespace ECommerceApi.JJHH17.Controllers;

[ApiController]
[Route("api/[controller]")]
// Example call: http://localhost:5609/api/product/
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}

[HttpGet]
public ActionResult<PagedResponse<GetProductsDto>> GetAllProducts([FromQuery] Pagination pagination)
{
if (pagination.PageNumber < 1) pagination.PageNumber = 1;
if (pagination.PageSize < 1) pagination.PageSize = 10;

var allProducts = _productService.GetAllProducts();

var totalRecords = allProducts.Count;
var pagedData = allProducts
.OrderBy(c => c.productId)
.Skip((pagination.PageNumber - 1) * pagination.PageSize)
.Take(pagination.PageSize)
.ToList();

return Ok(pagedData);
}

[HttpGet("{id}")]
public ActionResult<Product> GetProductById(int id)
{
var result = _productService.GetProductById(id);

if (result == null) { return NotFound(); }

return Ok(result);
}

[HttpPost]
public ActionResult<CreateProductDto> CreateProduct(CreateProductDto product)
{
return Ok(_productService.CreateProduct(product));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 CreatedAt

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using ECommerceApi.JJHH17.Models;
using ECommerceApi.JJHH17.Services;
using Microsoft.AspNetCore.Mvc;

namespace ECommerceApi.JJHH17.Controllers
{
Comment on lines +5 to +6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
namespace ECommerceApi.JJHH17.Controllers
{
namespace ECommerceApi.JJHH17.Controllers;

[ApiController]
[Route("api/[controller]")]
// Example call: http://localhost:5609/api/sale/
public class SalesController : ControllerBase
{
private readonly ISaleService _saleService;
public SalesController(ISaleService saleService)
{
_saleService = saleService;
}

[HttpGet]
public ActionResult<PagedResponse<GetProductsDto>> GetAllSales([FromQuery] Pagination pagination)
{
if (pagination.PageNumber < 1) pagination.PageNumber = 1;
if (pagination.PageSize < 1) pagination.PageSize = 10;

var allSales = _saleService.GetAllSales();

var totalRecords = allSales.Count;
var pagedData = allSales
.OrderBy(c => c.SaleId)
.Skip((pagination.PageNumber - 1) * pagination.PageSize)
.Take(pagination.PageSize)
.ToList();

return Ok(pagedData);
}

[HttpGet("{id}")]
public ActionResult<Sale> GetSaleById(int id)
{
var result = _saleService.GetSaleById(id);

if (result == null) { return NotFound(); }

return Ok(result);
}

[HttpPost]
public ActionResult<SaleWithProductsDto> CreateSale([FromBody] CreateSaleDto sale)
{
try
{
var created = _saleService.CreateSale(sale);

var dto = new SaleWithProductsDto(
created.SaleId,
created.ItemCount,
created.SalePrice,
created.Products
.OrderBy(p => p.ProductName)
.Select(p => new ProductDto(p.ProductId, p.ProductName, p.Price))
.ToList()
);

return CreatedAtAction(nameof(GetSaleById), new { id = created.SaleId }, dto);
}
catch (ArgumentNullException e)
{
return BadRequest(new { error = e.Message });
}
catch (ArgumentException ex)
{
return BadRequest(new { error = ex.Message });
}
catch (InvalidOperationException ex)
{
return NotFound(new { error = ex.Message });
}
Comment on lines +65 to +76

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Exception Handling

💡 The only method in your API controllers with a try catch block, and some weird exception handling. Seems like a bit of a code smell. Is there another more elegant way you could have handled these edge-cases?

}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading