What is Minimal API in .NET?
Minimal API is a lightweight way to build HTTP APIs in .NET (introduced in .NET 6).
It allows you to create REST APIs with less code, without Controllers, Startup class, or complex structure.
👉 Best for:
- Microservices
- Small REST APIs
- Backend for Angular/React apps
🔥 Traditional API vs Minimal API
| Traditional ASP.NET Core | Minimal API |
|---|---|
| Uses Controllers | No Controllers |
| Uses Startup.cs | No Startup.cs |
| More boilerplate code | Very less code |
| Better for large apps | Best for small/medium APIs |
Step by Step Implementation
- Create .NET Core API based Project
- Go into Program.cs
- Write only this code
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
- Run the application
Step by Step CRUD Operation (Minimal API)
Install Swagger Package: Swashbuckle.AspNetCore
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
List<Student> students = new()
{
new Student(1, "Shiva", 22),
new Student(2, "Rahul", 23)
};
// GET all students
app.MapGet("/students", () => students);
// GET by ID
app.MapGet("/students/{id}", (int id) =>
{
var student = students.FirstOrDefault(s => s.Id == id);
return student is not null ? Results.Ok(student) : Results.NotFound();
});
// POST
app.MapPost("/students", (Student student) =>
{
students.Add(student);
return Results.Created($"/students/{student.Id}", student);
});
// PUT
app.MapPut("/students/{id}", (int id, Student updatedStudent) =>
{
var student = students.FirstOrDefault(s => s.Id == id);
if (student is null)
return Results.NotFound();
students.Remove(student);
students.Add(updatedStudent);
return Results.Ok(updatedStudent);
});
// DELETE
app.MapDelete("/students/{id}", (int id) =>
{
var student = students.FirstOrDefault(s => s.Id == id);
if (student is null)
return Results.NotFound();
students.Remove(student);
return Results.Ok();
});
app.Run();
public record Student(int Id, string Name, int Age);
example with database and JWT token:
Create Model Class:
using System;
using System.Collections.Generic;
namespace DbFirstApproachExample.Models;
public partial class Dept
{
public int DeptId { get; set; }
public string? DeptName { get; set; }
}
Create CollegeDBContext:
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace DbFirstApproachExample.Models;
public partial class CollegeDbContext : DbContext
{
public CollegeDbContext()
{
}
public CollegeDbContext(DbContextOptions<CollegeDbContext> options)
: base(options)
{
}
public virtual DbSet<Course> Courses { get; set; }
public virtual DbSet<Department> Departments { get; set; }
public virtual DbSet<Dept> Depts { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>(entity =>
{
entity.HasKey(e => e.Courseid).HasName("PK__course__2AAB4BC9415F9615");
entity.ToTable("course");
entity.Property(e => e.Courseid).HasColumnName("courseid");
entity.Property(e => e.Coursedescription)
.IsUnicode(false)
.HasColumnName("coursedescription");
entity.Property(e => e.Coursefee)
.HasColumnType("numeric(10, 2)")
.HasColumnName("coursefee");
entity.Property(e => e.Coursename)
.IsUnicode(false)
.HasColumnName("coursename");
entity.Property(e => e.CreatedDate).HasDefaultValueSql("(getdate())");
});
modelBuilder.Entity<Department>(entity =>
{
entity.HasKey(e => e.DepartmentId).HasName("PK__Departme__B2079BED66A728F6");
entity.Property(e => e.DepartmentName)
.HasMaxLength(100)
.IsUnicode(false);
});
modelBuilder.Entity<Dept>(entity =>
{
entity.HasKey(e => e.DeptId).HasName("PK__Dept__0148818ECD91A34F");
entity.ToTable("Dept");
entity.Property(e => e.DeptId)
.ValueGeneratedNever()
.HasColumnName("DeptID");
entity.Property(e => e.DeptName)
.HasMaxLength(100)
.IsUnicode(false);
});
modelBuilder.Entity<Employee>(entity =>
{
entity.HasKey(e => e.EmpId).HasName("PK__Employee__AF2DBA7945912E83");
entity.ToTable("Employee");
entity.Property(e => e.EmpId)
.ValueGeneratedNever()
.HasColumnName("EmpID");
entity.Property(e => e.DeptId).HasColumnName("DeptID");
entity.Property(e => e.EmpName)
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.MgrId).HasColumnName("MgrID");
});
modelBuilder.Entity<Student>(entity =>
{
entity.HasKey(e => e.StudentId).HasName("PK__Students__32C52B990AEE1338");
entity.Property(e => e.Email)
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.MobileNo)
.HasMaxLength(15)
.IsUnicode(false);
entity.Property(e => e.StudentName)
.HasMaxLength(100)
.IsUnicode(false);
entity.HasOne(d => d.Department).WithMany(p => p.Students)
.HasForeignKey(d => d.DepartmentId)
.HasConstraintName("FK_Students_Departments");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
In ASP.NET Core Minimal API, you can secure your /depts endpoints using JWT Bearer Authentication.
Your existing .RequireAuthorization() is correct, but you need to configure JWT authentication, generate a token after login, and send that token in API requests.
1. Install NuGet Package
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
2. Configure JWT Authentication in Program.cs
Add the following configuration before builder.Build().
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<CollegeDbContext>(options =>
{
// Your existing DbContext configuration
});
// JWT Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "CollegeAPI",
ValidAudience = "CollegeClient",
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(
builder.Configuration["Jwt:Key"]!))
};
});
// Authorization
builder.Services.AddAuthorization();
var app = builder.Build();
// Authentication middleware
app.UseAuthentication();
app.UseAuthorization();
3. Add JWT Key in appsettings.json
{
"Jwt": {
"Key": "CollegeAPI_SuperSecret_Key_2026_123456789"
}
}
For production, keep the secret key in User Secrets, environment variables,
or a secure vault instead of committing it to source control.
4. Create JWT Token API (Login)
Add the following endpoint to generate a JWT token.
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
app.MapPost("/login", (string username, string password,
IConfiguration config) =>
{
// Demo credentials only
if (username != "admin" || password != "123")
return Results.Unauthorized();
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, "Admin")
};
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(config["Jwt:Key"]!));
var credentials = new SigningCredentials(
key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "CollegeAPI",
audience: "CollegeClient",
claims: claims,
expires: DateTime.UtcNow.AddMinutes(30),
signingCredentials: credentials);
var tokenString = new JwtSecurityTokenHandler()
.WriteToken(token);
return Results.Ok(new
{
token = tokenString,
expiration = token.ValidTo
});
});
5. Modify Your Department APIs
Best approach: Use MapGroup() and apply .RequireAuthorization() once.
This protects all department endpoints automatically.
var deptApi = app.MapGroup("/depts")
.RequireAuthorization();
// GET All Departments
deptApi.MapGet("/", async (CollegeDbContext db) =>
await db.Depts.ToListAsync());
// GET Department By ID
deptApi.MapGet("/{id:int}",
async (int id, CollegeDbContext db) =>
{
var data = await db.Depts.FindAsync(id);
return data is not null
? Results.Ok(data)
: Results.NotFound();
});
// POST Department
deptApi.MapPost("/", async (Dept d, CollegeDbContext db) =>
{
db.Depts.Add(d);
await db.SaveChangesAsync();
return Results.Created($"/depts/{d.DeptId}", d);
});
// PUT Department
deptApi.MapPut("/{id:int}",
async (int id, Dept d, CollegeDbContext db) =>
{
var data = await db.Depts.FindAsync(id);
if (data is null)
return Results.NotFound();
data.DeptName = d.DeptName;
await db.SaveChangesAsync();
return Results.Ok(new
{
message = "Data Updated Successfully"
});
});
// DELETE Department
deptApi.MapDelete("/{id:int}",
async (int id, CollegeDbContext db) =>
{
var data = await db.Depts.FindAsync(id);
if (data is null)
return Results.NotFound();
db.Depts.Remove(data);
await db.SaveChangesAsync();
return Results.Ok(new
{
message = "Data Deleted Successfully"
});
});
app.Run();
6. Test Using Postman
Step 1: Generate Token
POST https://localhost:7001/loginBody → raw → JSON:
{
"username": "admin",
"password": "123"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"expiration": "2026-11-11T..."
}
Step 2: Call Department API
GET https://localhost:7001/deptsIn Postman:
Select Authorization tab.
Select Type → Bearer Token.
Paste the generated JWT token.
Click Send.
Step 3: Verify Authentication
Scenario
Response
Token valid
200 OK
Token missing
401 Unauthorized
Token invalid
401 Unauthorized
Token expired
401 Unauthorized
Authentication Flow
1. Login API
Username + Password
2. JWT Token
Server generates signed token
3. Postman / Client
Authorization: Bearer Token
4. Middleware Validation
Validate signature, expiry, issuer, audience
5. Department API
Access granted

0 تعليقات
POST Answer of Questions and ASK to Doubt