Crud in Asp.net web api through Clean Architecture.

Mushahid AbbasiMushahid Abbasi
4 min read

now create a crud through clean architecture

ChatGPT said:

ChatGPT

Implementing a CRUD application using Clean Architecture in ASP.NET Core involves organizing your codebase into distinct layers that separate concerns, making the application more maintainable and scalable. Clean Architecture promotes independence from frameworks, UI, databases, and external services, allowing for easier testing and adaptability to changes.

Overview of Clean Architecture

Clean Architecture is typically organized into several layers:

  1. Entities (Core/Domain Layer): This layer contains the business logic and entities (models) that are independent of any external dependencies.

  2. Use Cases (Application Layer): This layer contains the business rules, orchestrating the flow of data to and from entities. It’s where the use cases (interactors) are implemented.

  3. Interfaces (Interface Adapters/Infrastructure Layer): This layer adapts the data from the outer layers (e.g., API, UI, database) to the inner layers. It might include repositories, services, and other adapters.

  4. Presentation (API Layer): This layer deals with the user interface or API. It interacts with the application layer to execute use cases.

Step-by-Step Implementation

1. Create the ASP.NET Core Project

You can start by creating a solution with multiple projects representing the layers of Clean Architecture.

bashCopy codedotnet new sln -n CleanArchitectureExample
cd CleanArchitectureExample

dotnet new classlib -n Core
dotnet new classlib -n Application
dotnet new classlib -n Infrastructure
dotnet new webapi -n WebAPI

dotnet sln add Core/Application/Infrastructure/WebAPI

2. Define the Core Layer

The Core layer will contain the business entities and interfaces that are independent of any external dependencies.

Entities

csharpCopy codenamespace Core.Entities
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

Interfaces

Define repository interfaces in the Core layer.

csharpCopy codenamespace Core.Interfaces
{
    public interface IProductRepository
    {
        Task<Product> GetByIdAsync(int id);
        Task<List<Product>> GetAllAsync();
        Task<Product> AddAsync(Product product);
        Task UpdateAsync(Product product);
        Task DeleteAsync(int id);
    }
}

3. Define the Application Layer

This layer contains the use cases and business logic.

Use Cases

csharpCopy codeusing Core.Entities;
using Core.Interfaces;

namespace Application.UseCases
{
    public class ProductUseCase
    {
        private readonly IProductRepository _productRepository;

        public ProductUseCase(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }

        public async Task<Product> GetByIdAsync(int id)
        {
            return await _productRepository.GetByIdAsync(id);
        }

        public async Task<List<Product>> GetAllAsync()
        {
            return await _productRepository.GetAllAsync();
        }

        public async Task<Product> AddAsync(Product product)
        {
            return await _productRepository.AddAsync(product);
        }

        public async Task UpdateAsync(Product product)
        {
            await _productRepository.UpdateAsync(product);
        }

        public async Task DeleteAsync(int id)
        {
            await _productRepository.DeleteAsync(id);
        }
    }
}

4. Define the Infrastructure Layer

This layer implements the repository interface, interacting with the database.

DbContext

csharpCopy codeusing Core.Entities;
using Microsoft.EntityFrameworkCore;

namespace Infrastructure.Data
{
    public class MyDbContext : DbContext
    {
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }

        public DbSet<Product> Products { get; set; }
    }
}

Repository Implementation

csharpCopy codeusing Core.Entities;
using Core.Interfaces;
using Infrastructure.Data;
using Microsoft.EntityFrameworkCore;

namespace Infrastructure.Repositories
{
    public class ProductRepository : IProductRepository
    {
        private readonly MyDbContext _context;

        public ProductRepository(MyDbContext context)
        {
            _context = context;
        }

        public async Task<Product> GetByIdAsync(int id)
        {
            return await _context.Products.FindAsync(id);
        }

        public async Task<List<Product>> GetAllAsync()
        {
            return await _context.Products.ToListAsync();
        }

        public async Task<Product> AddAsync(Product product)
        {
            _context.Products.Add(product);
            await _context.SaveChangesAsync();
            return product;
        }

        public async Task UpdateAsync(Product product)
        {
            _context.Entry(product).State = EntityState.Modified;
            await _context.SaveChangesAsync();
        }

        public async Task DeleteAsync(int id)
        {
            var product = await _context.Products.FindAsync(id);
            if (product != null)
            {
                _context.Products.Remove(product);
                await _context.SaveChangesAsync();
            }
        }
    }
}

5. Define the Web API Layer

This layer is the entry point where the API endpoints are defined. The controller interacts with the application layer to execute use cases.

Startup Configuration

First, register the DbContext and repository in Program.cs:

csharpCopy codevar builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<MyDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddScoped<IProductRepository, ProductRepository>();
builder.Services.AddScoped<ProductUseCase>();

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();

app.MapControllers();

app.Run();

Product Controller

csharpCopy codeusing Application.UseCases;
using Core.Entities;
using Microsoft.AspNetCore.Mvc;

namespace WebAPI.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class ProductsController : ControllerBase
    {
        private readonly ProductUseCase _productUseCase;

        public ProductsController(ProductUseCase productUseCase)
        {
            _productUseCase = productUseCase;
        }

        [HttpGet]
        public async Task<IActionResult> GetAll()
        {
            var products = await _productUseCase.GetAllAsync();
            return Ok(products);
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetById(int id)
        {
            var product = await _productUseCase.GetByIdAsync(id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }

        [HttpPost]
        public async Task<IActionResult> Create(Product product)
        {
            var createdProduct = await _productUseCase.AddAsync(product);
            return CreatedAtAction(nameof(GetById), new { id = createdProduct.Id }, createdProduct);
        }

        [HttpPut("{id}")]
        public async Task<IActionResult> Update(int id, Product product)
        {
            if (id != product.Id)
            {
                return BadRequest();
            }

            await _productUseCase.UpdateAsync(product);
            return NoContent();
        }

        [HttpDelete("{id}")]
        public async Task<IActionResult> Delete(int id)
        {
            await _productUseCase.DeleteAsync(id);
            return NoContent();
        }
    }
}

6. Run the Application

Once everything is set up, run the application:

bashCopy codedotnet run --project WebAPI

You can now test the CRUD operations through the API endpoints using tools like Postman or Swagger.

Summary

This guide demonstrates how to structure a CRUD application using Clean Architecture in ASP.NET Core. By separating concerns across different layers (Core, Application, Infrastructure, and WebAPI), you create a scalable and maintainable application that is independent of external frameworks and technologies.

0
Subscribe to my newsletter

Read articles from Mushahid Abbasi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mushahid Abbasi
Mushahid Abbasi