Minimal APIs in ASP.NET Core

Introduction
Minimal APIs, introduced in .NET 6, provide a lightweight approach to building HTTP APIs with minimal setup and configuration. They simplify the development of microservices and small APIs by reducing boilerplate code and focusing on the essentials. This guide will walk you through the concepts, advantages, and implementation of Minimal APIs in ASP.NET Core.
Why Minimal APIs?
Simplified Syntax: Write less code to achieve the same functionality.
Performance: Optimized for high-performance scenarios.
Quick Start: Ideal for small, lightweight, and rapid-development projects.
Microservices-Friendly: Perfect for building modular, focused APIs.
Key Features
No Startup.cs or Controller Classes: Everything can be handled in Program.cs.
Direct Mapping: Define routes directly in the code.
Integrated Dependency Injection.
OpenAPI/Swagger Support.
Middleware Integration.
Setting Up a Minimal API Project
Prerequisites:
- .NET SDK 6.0 or later
Steps:
Create a New Project:
dotnet new web -n MinimalApiDemo
cd MinimalApiDemo
Update Program.cs: Minimal APIs are defined in the Program.cs file.
Code Walkthrough
Here’s a step-by-step example to create a basic CRUD API for managing products.
1. Define the Model
Create a Product model in the Models folder:
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}
2. Configure Dependency Injection
Simulate a database using an in-memory list in Program.cs:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container
builder.Services
.AddSingleton<List<Product>>();
var app =
builder.Build
();
3. Define Endpoints
Add endpoints to handle CRUD operations:
// GET all products
app.MapGet("/products", (List<Product> products) => Results.Ok(products));
// GET product by ID
app.MapGet("/products/{id}", (int id, List<Product> products) =>
{
var product = products.FirstOrDefault(p =>
p.Id
== id);
return product != null ? Results.Ok(product) : Results.NotFound();
});
// POST create a new product
app.MapPost("/products", (Product product, List<Product> products) =>
{
product.Id
= products.Count > 0 ? products.Max(p =>
p.Id
) + 1 : 1;
products.Add(product);
return Results.Created($"/products/{
product.Id
}", product);
});
// PUT update a product
app.MapPut("/products/{id}", (int id, Product updatedProduct, List<Product> products) =>
{
var product = products.FirstOrDefault(p =>
p.Id
== id);
if (product == null) return Results.NotFound();
product.Name
=
updatedProduct.Name
;
product.Price = updatedProduct.Price;
return Results.NoContent();
});
// DELETE a product
app.MapDelete("/products/{id}", (int id, List<Product> products) =>
{
var product = products.FirstOrDefault(p =>
p.Id
== id);
if (product == null) return Results.NotFound();
products.Remove(product);
return Results.NoContent();
});
4. Add Middleware
Add Swagger for API documentation:
// Enable Swagger
builder.Services
.AddEndpointsApiExplorer();
builder.Services
.AddSwaggerGen();
var app =
builder.Build
();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
5. Run the Application
Start the application and test the endpoints:
dotnet run
Access Swagger UI at: https://localhost:<port>/swagger
Advanced Features
1. Input Validation
Use FluentValidation for input validation:
builder.Services
.AddScoped<IValidator<Product>, ProductValidator>();
app.MapPost("/products", async (Product product, IValidator<Product> validator, List<Product> products) =>
{
var validationResult = await validator.ValidateAsync(product);
if (!validationResult.IsValid)
{
return Results.BadRequest(validationResult.Errors);
}
product.Id
= products.Count > 0 ? products.Max(p =>
p.Id
) + 1 : 1;
products.Add(product);
return Results.Created($"/products/{
product.Id
}", product);
});
2. Authentication and Authorization
Add JWT-based authentication:
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YourSecretKey"))
};
});
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/secure-products", [Authorize] (List<Product> products) => Results.Ok(products));
3. CORS Support
Enable Cross-Origin Resource Sharing:
builder.Services
.AddCors(options =>
{
options.AddPolicy("AllowAll", policy => policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
app.UseCors("AllowAll");
Conclusion
Minimal APIs in ASP.NET Core provide a streamlined approach to building lightweight APIs with minimal overhead. They are perfect for small-scale applications, microservices, or scenarios where simplicity is paramount. By integrating advanced features like authentication, validation, and middleware, Minimal APIs can be extended to handle complex use cases effectively.
References
Subscribe to my newsletter
Read articles from Ujwal Watgule directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
