Microservices in C# (.NET): Architecture and Practice

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Microservices in C# (.NET): From Theory to Practice



In modern software development, microservice architecture has become the standard for building scalable and fault-tolerant systems. The .NET platform provides all the necessary tools for creating reliable microservices in C#. In this article, we will explore key architectural principles, practical code examples, and best practices that will help you start building microservices in C#.



1. Fundamentals of Microservice Architecture in .NET



Microservices is a development approach where an application is divided into small, independent services, each responsible for its own business function. In the .NET ecosystem, ASP.NET Core is used for this purpose — a lightweight and cross-platform framework.



Key Principles of Microservices in C#:

  • Independent deployment — each service can be updated without stopping others.
  • Loose coupling — services communicate via API (REST, gRPC) or message queues.
  • Own database — each microservice owns its data (Database per Service).
  • Fault tolerance — failure of one service should not block the entire system.


Let's start by creating a simple microservice in C#. We'll use the ASP.NET Core Web API template.



// Creating a new microservice projectdotnet new webapi -n OrderServicecd OrderService

// Example of a simple controller[ApiController][Route("api/[controller]")]public class OrdersController : ControllerBase{ private readonly IOrderRepository _repository;

public OrdersController(IOrderRepository repository) { _repository = repository; }

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

[HttpPost] public async Task<IActionResult> CreateOrder(OrderDto orderDto) { var order = new Order(orderDto.CustomerId, orderDto.TotalAmount); await _repository.AddAsync(order); return CreatedAtAction(nameof(GetOrder), new { id = order.Id }, order); }}


2. Inter-Service Communication: REST, gRPC, and Queues



Microservices need to communicate with each other. In .NET, three main approaches are available:



REST API (HTTP)

The simplest and most common method. Use HttpClient with a factory for proper connection management.



// Example of calling another microservice via HttpClientpublic class InventoryServiceClient{    private readonly HttpClient _httpClient;

public InventoryServiceClient(HttpClient httpClient) { _httpClient = httpClient; }

public async Task<bool> CheckStockAsync(int productId, int quantity) { var response = await _httpClient.GetAsync( $"/api/inventory/check?productId={productId}&quantity={quantity}"); return response.IsSuccessStatusCode; }}

// Registration in Program.csbuilder.Services.AddHttpClient<InventoryServiceClient>(client =>{ client.BaseAddress = new Uri("http://inventory-service:5001");});


gRPC

For high-performance synchronous communication, use gRPC. It is based on HTTP/2 and Protocol Buffers.



// Service definition in .proto filesyntax = "proto3";

service OrderProcessor { rpc ProcessOrder (OrderRequest) returns (OrderResponse);}

message OrderRequest { int32 order_id = 1; string customer_email = 2;}

message OrderResponse { bool success = 1; string message = 2;}

// Server-side implementation in C#public class OrderProcessorService : OrderProcessor.OrderProcessorB

Blogs

Book Recommendations