
In modern web development, scalability, flexibility, and maintainability are key challenges. A microservices architecture offers a way to break monolithic applications into independently deployable services, improving scalability and team productivity.
Blazor, part of .NET 8, is an advanced UI framework that enables full-stack C# development, allowing developers to build interactive web applications that consume microservices via REST APIs, gRPC, and event-driven messaging.
In this article, we’ll explore how Blazor and microservices work together, discuss API integration patterns, and walk through code examples to build a real-world scalable application.
Why Use Blazor with Microservices?
- Separation of Concerns: Frontend (Blazor) is decoupled from backend services.
- Scalability: Individual microservices can scale independently.
- Resilience: Failure in one service doesn’t affect the entire application.
- Technology Agnostic: Different services can use different stacks.
- Developer Productivity: Teams can work on separate microservices without conflicts.
Blazor and Microservices Architecture Overview
.NET 8 Blazor microservices-based solutions typically consist of the following:
- Blazor Frontend — A client-side UI built with Blazor WebAssembly or Blazor Server.
- API Gateway — A centralized point for routing requests to microservices (e.g., Ocelot, YARP).
- Microservices — Independent backend services exposing REST APIs or gRPC endpoints.
- Database Per Service — Each microservice can have its own database (SQL Server, PostgreSQL, MongoDB, etc.).
- Event-Driven Messaging — Services communicate asynchronously using RabbitMQ, Kafka, or Azure Service Bus.
Technology Stack
- Frontend: Blazor WebAssembly (WASM) or Blazor Server
- Backend: ASP.NET Core Web API Microservices
- Database: SQL Server, PostgreSQL, MongoDB
- API Gateway: Ocelot, YARP
- Authentication: IdentityServer, Azure AD
- Message Broker: RabbitMQ, Kafka
1️⃣Building a Microservice with .NET 8
We’ll start by creating an Orders Microservice in ASP.NET Core Web API.
Install the required packages
dotnet new webapi -n OrdersService
cd OrdersService
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Swashbuckle.AspNetCore
Define the Order Model
Models/Order.cs
public class Order
{
public int Id { get; set; }
public string Product { get; set; }
public int Quantity { get; set; }
}
Create the Orders API Controller
This microservice exposes an API endpoint:
GET /api/orders/{id}
[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
private static readonly List<Order> Orders = new()
{
new Order { Id = 1, Product = "Laptop", Quantity = 1 },
new Order { Id = 2, Product = "Smartphone", Quantity = 2 }
};
[HttpGet("{id}")]
public IActionResult GetOrder(int id)
{
var order = Orders.FirstOrDefault(o => o.Id == id);
if (order == null) return NotFound();
return Ok(order);
}
}
2️⃣Consuming Microservices in Blazor
Inject HttpClient in Blazor
Program.cs
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("https://localhost:5001") });
Call the API in a Blazor Component
Clicking Get Order fetches and displays the order details.
@inject HttpClient Http
<h3>Order Details</h3>
<p>@OrderDetails</p>
<button @onclick="LoadOrder">Get Order</button>
@code {
private string OrderDetails = "Click to load order...";
private async Task LoadOrder()
{
var order = await Http.GetFromJsonAsync<Order>("api/orders/1");
OrderDetails = $"Product: {order.Product}, Quantity: {order.Quantity}";
}
public class Order
{
public string Product { get; set; }
public int Quantity { get; set; }
}
}
3️⃣Implementing an API Gateway (Ocelot)
An API Gateway routes requests from Blazor to the appropriate microservice.
Install Ocelot
dotnet add package Ocelot.AspNetCore
Define Ocelot Configuration
ocelot.json
{
"Routes": [
{
"DownstreamPathTemplate": "/api/orders/{id}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [{ "Host": "localhost", "Port": 5001 }],
"UpstreamPathTemplate": "/orders/{id}",
"UpstreamHttpMethod": [ "GET" ]
}
]
}
Configure Ocelot in Program.cs
Blazor only needs to call
/orders/{id}, and Ocelot routes it to the right microservice.
builder.Services.AddOcelot();
app.UseOcelot().Wait();
4️⃣Event-Driven Microservices with RabbitMQ
Instead of synchronous API calls, we can use event-driven messaging.
Publish an Order Created Event
OrderService
public void PublishOrderCreatedEvent(int orderId)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare(queue: "order_events", durable: false, exclusive: false, autoDelete: false);
string message = JsonSerializer.Serialize(new { OrderId = orderId });
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "", routingKey: "order_events", body: body);
}
Subscribe in Blazor
Now Blazor reacts to order events asynchronously
public class OrderListenerService : BackgroundService
{
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare(queue: "order_events", durable: false, exclusive: false, autoDelete: false);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"Received: {message}");
};
channel.BasicConsume(queue: "order_events", autoAck: true, consumer: consumer);
return Task.CompletedTask;
}
}
Extending .NET 8 Blazor and Microservices with gRPC and Kubernetes
Extending microservices with gRPC enables high-performance communication, while Kubernetes automates deployment and orchestration. By integrating these technologies, you can build a scalable, efficient, and resilient microservices architecture. In this article, we’ll explore how to enhance .NET 8 microservices with gRPC for fast communication and Kubernetes for seamless deployment.
5️⃣Using gRPC for Faster Microservice Communication
While REST APIs are common, gRPC (gRPC Remote Procedure Calls) offers higher performance, lower latency, and strong type safety, making it ideal for microservices.
Why Use gRPC?
- Efficient Binary Serialization (Protocol Buffers) — Faster than JSON
- Strongly Typed Contracts — Enforced via
.protofiles - Streaming Support – Ideal for real-time applications
- Multiplexing – Multiple requests over a single connection
Step 1: Create a gRPC Microservice
dotnet new grpc -n OrdersGrpcService
cd OrdersGrpcService
Step 2: Define the gRPC Service
Protos/orders.proto
syntax = "proto3";
service OrderService {
rpc GetOrder (OrderRequest) returns (OrderResponse);
}
message OrderRequest {
int32 id = 1;
}
message OrderResponse {
int32 id = 1;
string product = 2;
int32 quantity = 3;
}
Step 3: Implement gRPC Service
Services/OrderService.cs
public class OrderService : OrderServiceBase
{
private readonly List<Order> _orders = new()
{
new() { Id = 1, Product = "Laptop", Quantity = 1 },
new() { Id = 2, Product = "Smartphone", Quantity = 2 }
};
public override Task<OrderResponse> GetOrder(OrderRequest request, ServerCallContext context)
{
var order = _orders.FirstOrDefault(o => o.Id == request.Id);
return Task.FromResult(order == null
? new OrderResponse()
: new OrderResponse { Id = order.Id, Product = order.Product, Quantity = order.Quantity });
}
}
Step 4: Configure gRPC in Program.cs
Now the microservice exposes gRPC endpoints
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<OrderService>();
app.Run();
6️⃣Consuming gRPC in Blazor
gRPC is a high-performance, open-source RPC framework that enables efficient, cross-platform communication between microservices using protocol buffers and HTTP/2.
Step 1: Install gRPC Client Packages
dotnet add package Grpc.Net.Client
dotnet add package Grpc.Tools
Step 2: Add gRPC Client
Program.cs
builder.Services.AddSingleton(services =>
{
var channel = GrpcChannel.ForAddress("https://localhost:5001");
return new OrderService.OrderServiceClient(channel);
});
Step 3: Call gRPC in Blazor
Blazor now fetches orders using gRPC, which is faster and more efficient than REST
@inject OrderService.OrderServiceClient OrderClient
<h3>Order Details</h3>
<p>@OrderDetails</p>
<button @onclick="LoadOrder">Get Order</button>
@code {
private string OrderDetails = "Click to load order...";
private async Task LoadOrder()
{
var request = new OrderRequest { Id = 1 };
var response = await OrderClient.GetOrderAsync(request);
OrderDetails = $"Product: {response.Product}, Quantity: {response.Quantity}";
}
}
7️⃣Deploying Microservices with Kubernetes
Kubernetes (K8s) automates deployment, scaling, and management of microservices.
Step 1: Create a Dockerfile for Orders API
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY ./bin/Release/net8.0/publish/ .
ENTRYPOINT ["dotnet", "OrdersService.dll"]
Step 2: Create a Kubernetes Deployment
orders-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-service
spec:
replicas: 2
selector:
matchLabels:
app: orders-service
template:
metadata:
labels:
app: orders-service
spec:
containers:
- name: orders-service
image: myregistry/orders-service:latest
ports:
- containerPort: 80
Step 3: Apply to Kubernetes
Now the Orders Microservice is deployed on Kubernetes
kubectl apply -f orders-deployment.yaml
Combining .NET 8, Blazor, and microservices enables highly scalable, resilient applications. By integrating API Gateways, asynchronous messaging, and Blazor UI, we create a modern, decoupled architecture for future-proof applications.
Using .NET 8, Blazor, Microservices, gRPC, and Kubernetes, we’ve built a scalable, fast, and cloud-native application. Blazor provides a powerful UI, gRPC ensures high-performance communication, and Kubernetes handles deployment and scaling.