Layered, or N-Tier Architecture, is a traditional software design pattern that organizes an application into logical layers, each with a specific responsibility. This approach improves the separation of concerns, making the application easier to manage, test, and extend. Each layer in the architecture typically only interacts with the layer directly above or below it.
In this blog, we'll explore how to build a Product and Order service using Layered Architecture in .NET Core. We'll break down each layer, explain its purpose, and provide code examples to demonstrate how the layers interact.
What is Layered (N-Tier) Architecture?
Layered Architecture divides an application into layers, where each layer has a specific role and responsibility. The layers in a typical N-Tier architecture might include.
- Presentation Layer: Manages user interactions, typically through a web interface or API.
- Application Layer: Coordinates application activities, processing business logic, and handling transactions.
- Business Logic Layer (BLL): Encapsulates core business rules and logic.
- Data Access Layer (DAL): Handles database operations and data persistence.
- Database Layer: The actual database where data is stored.
This layered approach helps ensure that each part of the application is focused on a single aspect of functionality, improving maintainability and testability.
Setting Up the Project
Let's build a Product and Order service using a Layered Architecture. We'll create a .NET Core solution with four projects to represent each layer.
- Presentation Layer: Exposes API endpoints.
- Application Layer: Manages the application's workflows.
- Business Logic Layer (BLL): Contains business logic.
- Data Access Layer (DAL): Interfaces with the database.
1. Presentation Layer
The Presentation Layer is responsible for handling user interactions. In our case, this is a Web API that exposes endpoints for managing products and orders.
API Controllers
using Microsoft.AspNetCore.Mvc;
using ProductOrder.Application.Interfaces;
using ProductOrder.Application.DTOs;
namespace ProductOrder.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetProduct(Guid id)
{
var product = await _productService.GetProductByIdAsync(id);
if (product == null) return NotFound();
return Ok(product);
}
[HttpPost]
public async Task<IActionResult> CreateProduct([FromBody] ProductDto productDto)
{
var product = await _productService.AddProductAsync(productDto);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
// Additional actions...
}
[Route("api/[controller]")]
[ApiController]
public class OrdersController : ControllerBase
{
private readonly IOrderService _orderService;
public OrdersController(IOrderService orderService)
{
_orderService = orderService;
}
[HttpPost]
public async Task<IActionResult> CreateOrder(Guid productId, int quantity)
{
var order = await _orderService.CreateOrderAsync(productId, quantity);
return CreatedAtAction(nameof(GetOrder), new { id = order.Id }, order);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetOrder(Guid id)
{
var order = await _orderService.GetOrderByIdAsync(id);
if (order == null) return NotFound();
return Ok(order);
}
// Additional actions...
}
}
2. Application Layer
The Application Layer manages the workflows of the application. It handles the orchestration of business logic and data access.
Application Services
using ProductOrder.Application.Interfaces;
using ProductOrder.Application.DTOs;
using ProductOrder.BLL.Interfaces;
namespace ProductOrder.Application.Services
{
public class ProductService : IProductService
{
private readonly IProductManager _productManager;
public ProductService(IProductManager productManager)
{
_productManager = productManager;
}
public async Task<ProductDto> GetProductByIdAsync(Guid id)
{
var product = await _productManager.GetByIdAsync(id);
return new ProductDto
{
Id = product.Id,
Name = product.Name,
Price = product.Price
};
}
public async Task<ProductDto> AddProductAsync(ProductDto productDto)
{
var product = new Product
{
Name = productDto.Name,
Price = productDto.Price
};
await _productManager.AddAsync(product);
return new ProductDto
{
Id = product.Id,
Name = product.Name,
Price = product.Price
};
}
// Additional methods...
}
public class OrderService : IOrderService
{
private readonly IOrderManager _orderManager;
private readonly IProductManager _productManager;
public OrderService(IOrderManager orderManager, IProductManager productManager)
{
_orderManager = orderManager;
_productManager = productManager;
}
public async Task<OrderDto> CreateOrderAsync(Guid productId, int quantity)
{
var product = await _productManager.GetByIdAsync(productId);
if (product == null) throw new Exception("Product not found");
var order = new Order
{
ProductId = productId,
Quantity = quantity,
OrderDate = DateTime.UtcNow,
Product = product
};
await _orderManager.AddAsync(order);
return new OrderDto
{
Id = order.Id,
ProductId = order.ProductId,
Quantity = order.Quantity,
Total = order.Total,
OrderDate = order.OrderDate
};
}
// Additional methods...
}
}

vaibhav khairnarPosted Jan 19, 2025, 4:32 PM
Thanks you so much. I was not getting how to call DAL layer service from BL but after much search got this post
Mariusz PostolPosted Sep 3, 2024, 9:47 AM
"Database Layer: The actual database where data is stored." is it a software layer?