DEV Community

Cover image for Creating a RESTful API with .NET and Clean Architecture: A Complete Guide 🚀
0x2e73
0x2e73

Posted on • Edited on

Creating a RESTful API with .NET and Clean Architecture: A Complete Guide 🚀

Hey there! 👋 Are you tired of messy code shit architectures? Well, let’s fix that! In this post, we’ll walk through creating a RESTful API using Clean Architecture with .NET 8. By the end, you’ll have a modular, scalable, and super clean API, which means less stress for you and more time to enjoy your coffee ☕. Let’s dive in!

Wtf is clean architecture ?

You might be wondering, "Why should I bother with Clean Architecture? Isn’t my code already fine?" 🤔 Well, no, your code is bad, but its not important, mine is not better. Clean Architecture helps separate concerns into distinct layers, making your code more maintainable, testable, and future-proof. Plus, it gives you that “I’ve got everything under control” feeling. 😉

Clean Architecture is like a neat apartment: when it’s organized, you can find anything easily. When it’s messy? You end up searching for your keys for 20 minutes (we've all been there 🙈).

The Layers of Clean Architecture

Here’s a quick rundown of the layers in Clean Architecture:

  1. Core: Where the magic happens – your entities and interfaces.
  2. Application: This layer handles business logic (services, use cases), talking to Core through interfaces.
  3. Infrastructure: The concrete stuff – think databases, third-party APIs, and services.
  4. WebApi: The shiny API layer that interacts with the outside world (a.k.a. your clients).

Image description

Steps to Create the API 🚧

lets code !

Creating the Project

First, let’s start by setting up the foundation (i.e. the cool house we’re building 🏠). Open up a terminal and create the projects:

dotnet new sln -n MyCleanApi dotnet new classlib -n MyCleanApi.Core dotnet new classlib -n MyCleanApi.Application dotnet new classlib -n MyCleanApi.Infrastructure dotnet new webapi -n MyCleanApi.WebApi dotnet sln MyCleanApi.sln add MyCleanApi.Core/MyCleanApi.Core.csproj dotnet sln MyCleanApi.sln add MyCleanApi.Application/MyCleanApi.Application.csproj dotnet sln MyCleanApi.sln add MyCleanApi.Infrastructure/MyCleanApi.Infrastructure.csproj dotnet sln MyCleanApi.sln add MyCleanApi.WebApi/MyCleanApi.WebApi.csproj 
Enter fullscreen mode Exit fullscreen mode

This will create four projects:

  • Core: The brains 💡 of your app (entities and interfaces).
  • Application: Where the business logic happens (the magic ✨).
  • Infrastructure: The hands-on stuff (database, external APIs).
  • WebApi: The gateway to your API (like the doorman at a fancy restaurant 🏙️).

Define the Entities (Core) 🏢

In Core, define a simple Product entity (because who doesn’t love products, right? 😄).

namespace MyCleanApi.Core.Entities { public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } } 
Enter fullscreen mode Exit fullscreen mode

Define Repository Interfaces (Core) 📚

In Core, define the repository interface to manage your Products. This will act like the API to interact with your data.

namespace MyCleanApi.Core.Interfaces { public interface IProductRepository { Task<IEnumerable<Product>> GetAllAsync(); Task<Product> GetByIdAsync(int id); Task AddAsync(Product product); Task UpdateAsync(Product product); Task DeleteAsync(int id); } } 
Enter fullscreen mode Exit fullscreen mode

Create the Services (Application) 💼

In Application, create the service that will handle your business logic. This is the brains behind the operation. No stress, it’s like a superhero team!

namespace MyCleanApi.Application.Services { public class ProductService { private readonly IProductRepository _productRepository; public ProductService(IProductRepository productRepository) { _productRepository = productRepository; } public async Task<IEnumerable<Product>> GetAllProductsAsync() { return await _productRepository.GetAllAsync(); } public async Task<Product> GetProductByIdAsync(int id) { return await _productRepository.GetByIdAsync(id); } public async Task AddProductAsync(Product product) { await _productRepository.AddAsync(product); } public async Task UpdateProductAsync(Product product) { await _productRepository.UpdateAsync(product); } public async Task DeleteProductAsync(int id) { await _productRepository.DeleteAsync(id); } } } 
Enter fullscreen mode Exit fullscreen mode

Implement the Repository (Infrastructure) 🔧

In Infrastructure, implement the repository using Entity Framework (because EF is like the trusty sidekick of your app 🦸‍♂️).

namespace MyCleanApi.Infrastructure.Repositories { public class ProductRepository : IProductRepository { private readonly AppDbContext _context; public ProductRepository(AppDbContext context) { _context = context; } public async Task<IEnumerable<Product>> GetAllAsync() { return await _context.Products.ToListAsync(); } public async Task<Product> GetByIdAsync(int id) { return await _context.Products.FindAsync(id); } public async Task AddAsync(Product product) { await _context.Products.AddAsync(product); await _context.SaveChangesAsync(); } public async Task UpdateAsync(Product product) { _context.Products.Update(product); 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(); } } } } 
Enter fullscreen mode Exit fullscreen mode

Set Up the Database Context (Infrastructure) 🏗️

Now, let’s make sure the database can handle the Products we’re going to throw at it (it’s tough, don’t worry 😆).

namespace MyCleanApi.Infrastructure { public class AppDbContext : DbContext { public DbSet<Product> Products { get; set; } public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } } } 
Enter fullscreen mode Exit fullscreen mode

Set Up Dependency Injection (WebApi) 🤖

In WebApi, we need to configure dependency injection so everything talks to each other (because even APIs need friends 🫶).

builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddScoped<IProductRepository, ProductRepository>(); builder.Services.AddScoped<ProductService>(); 
Enter fullscreen mode Exit fullscreen mode

Create the API Endpoints (WebApi) 📡

Now, let’s expose the API! This is where you handle HTTP requests. We’ll set up the basic CRUD operations for Product.

namespace MyCleanApi.WebApi.Controllers { [ApiController] [Route("api/[controller]")] public class ProductController : ControllerBase { private readonly ProductService _productService; public ProductController(ProductService productService) { _productService = productService; } [HttpGet] public async Task<IActionResult> GetAll() { var products = await _productService.GetAllProductsAsync(); return Ok(products); } [HttpGet("{id}")] public async Task<IActionResult> GetById(int id) { var product = await _productService.GetProductByIdAsync(id); if (product == null) return NotFound(); return Ok(product); } [HttpPost] public async Task<IActionResult> Create([FromBody] Product product) { await _productService.AddProductAsync(product); return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); } [HttpPut("{id}")] public async Task<IActionResult> Update(int id, [FromBody] Product product) { product.Id = id; await _productService.UpdateProductAsync(product); return NoContent(); } [HttpDelete("{id}")] public async Task<IActionResult> Delete(int id) { await _productService.DeleteProductAsync(id); return NoContent(); } } } 
Enter fullscreen mode Exit fullscreen mode

Testing and Running the API 🎯

Don’t forget to test everything! You can use Postman or any HTTP client to test your API. And remember: always check your database (it’s like checking if your fridge is full before cooking 😅).

Conclusion 🎉

Boom! You’ve now built a RESTful API with .NET and Clean Architecture. Your code is organized, scalable, and ready for future upgrades (like adding a robot army… just kidding… or not 🤖).

Let me know how it goes, or if you have any questions. Happy coding, and may your API requests always return 200 OK! 💻✨

Top comments (6)

Collapse
 
arashzandi profile image
Arash zandi

May you publish your codes to the github ?

Collapse
 
0x2e73 profile image
0x2e73

Yes, no problem, ill make a github repo and come back to you this afternoon ;)

Collapse
 
0x2e73 profile image
0x2e73

github.com/mou-inoks/clean-archite...

here, there is a bit more then in this guide.

Collapse
 
arashzandi profile image
Arash zandi

That deserves more than 10K github stars.🎉❤️🙏👏

Thread Thread
 
0x2e73 profile image
0x2e73

thank you very much for your comments appriciate it

Collapse
 
arashzandi profile image
Arash zandi

Thank you very much 🙏