DEV Community

Jervie Gono
Jervie Gono

Posted on

Part 2 of My First .NET Core Web API Project: Documenting the Rookie Mistakes and Wins on the Way to a Job.

Creating our Core Domain Entities

It can be challenging to choose our models.
You should consider the long-term effects before committing and making a decision. Initially, I made the decision to include numerous other options, like payment, shopping cart, product variant, product image, and so forth. However, I am aware that the project will take more than six months to complete, and as I am a lone developer, I may not be able to finish it.

Core/Entities and their relationship

> - Category
- > Contains products
- > Navigation: Products collection
- > Used by seller/admin to organize items
- > Self-referencing for subcategories

> - Product
- > Belongs to Category
- > Navigation: OrderItems, Reviews
- > Shown in shop menu to customers
- > Can be added/updated by seller

> - Order
- > Created when a customer buys items
- > Contains multiple OrderItems
- > Status tracks the overall order (Pending, Confirmed, Shipped, Delivered, Cancelled)
- > TotalAmount = sum of OrderItem.UnitPrice * Quantity
- > Managed mostly by backend (seller/admin)

> - OrderItem
- > Snapshot of a product at the time of order
- > Contains UnitPrice, Quantity
- > Navigation to Order and Product

> - Review
- > Written by customer
- > Only creation is needed (no update)
- > Linked to Product and User`
Enter fullscreen mode Exit fullscreen mode

Now that our model and entities are completed
We go on to our Dto. Data Transfer Object (DTO)
Planning is necessary in various ways.

//our Dtos category for httpPost
 public record CategoryRequestDto
 {
     public string Name { get; init; } = string.Empty;
     public string? Description { get; init; }
 }
Enter fullscreen mode Exit fullscreen mode

Why are records being used here?
Because we are striving for immutability, which classes do not have

PS: We also need to put Enums in Shared, Why? same reason for Dtos: Dependency Management.

Also, Enums often represent fundamental, non-changing data points that are used across multiple layers.

Validation

We're setting a standard here: Fluent Validation is our primary validation tool. While the built-in Data Annotations are fine for quick setups, we're phasing them out for consistency and enterprise readiness.

In the world of real-deal, production-level applications—especially larger ones—Fluent Validation is the industry favorite. Getting comfortable with its clear, code-based approach now is a huge win for future projects.

Sample code:

internal class CategoryRequestValidation : AbstractValidator<CategoryRequestDto>
{
    protected CategoryRequestValidation()
    {
        RuleFor(x => x.Name)
            .NotEmpty().WithMessage("Category name is required.")
            .MaximumLength(100).WithMessage("Category name must not exceed 100 characters.");

        RuleFor(x => x.Description)
            .MaximumLength(500).WithMessage("Category description must not exceed 500 characters.");
    }

}
Enter fullscreen mode Exit fullscreen mode

Lastly we just register it in our Dependency Injection

/// <summary>
/// Creates extension methods for registering services in the Infrastructure layer.
/// </summary>
public static class DependencyInjection
{
    public static IServiceCollection AddInfrastructure(this IServiceCollection services)
    {
        #region
        //Category Validation
        services.AddValidatorsFromAssemblyContaining<CategoryRequestValidation>();
        services.AddValidatorsFromAssemblyContaining<CategoryUpdateValidation>();
//The rest of Codes
Enter fullscreen mode Exit fullscreen mode

What's Next?

In Part 3, I'll dive into implementing the base architecture with:

  • Creating DbContext
  • Configuring Secret User
  • Registering services in Program.cs
  • Prepare for Identity

Top comments (0)