ASP.NET Core Minimal APIs provide a lightweight and efficient approach for building RESTful APIs with minimal boilerplate code.
Despite their simplicity, Minimal APIs support powerful features such as Middleware, Endpoint Filters, Dependency Injection, and Entity Framework Core integration.
What We Will Build
In this article, we will build a complete ASP.NET Core Minimal API example that includes:
- Custom Middleware
- Endpoint Filters
- Entity Framework Core
- SQL Server Integration
- Student CRUD APIs
1. RequestLoggingMiddleware Middleware
Middleware in ASP.NET Core works as part of the HTTP request pipeline. Every request passes through middleware components before reaching the endpoint.
In this middleware, we log:
- Request method
- Request path
- Response status code
RequestLoggingMiddleware.cs
namespace MiddlewareAndFiltersDemoWithDotNet.Middlewares
{
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
public RequestLoggingMiddleware(RequestDelegate next)
{
this._next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine($"Incoming Request: {context.Request.Method} {context.Request.Path}");
await _next(context);
Console.WriteLine($"Response Status: {context.Response.StatusCode}");
}
}
}
2. StudentValidationEndpointFilter Endpoint Filter
Endpoint Filters in Minimal APIs are useful for implementing:
- Validation
- Authorization
- Logging
- Request preprocessing
In this example, the endpoint filter validates that:
- Student name should not be empty
- Student email should not be empty
StudentValidationEndpointFilter.cs
using MiddlewareAndFiltersDemoWithDotNet.Models;
namespace MiddlewareAndFiltersDemoWithDotNet.EndpointFilters
{
public class StudentValidationEndpointFilter : IEndpointFilter
{
public async ValueTask<object?> InvokeAsync(
EndpointFilterInvocationContext context,
EndpointFilterDelegate next)
{
var student = context.GetArgument<Student>(0);
Dictionary<string, string[]> errors =
new Dictionary<string, string[]>();
if (string.IsNullOrWhiteSpace(student.Name))
{
errors.Add(nameof(student.Name),
new string[] { "Student name is required" });
}
if (string.IsNullOrWhiteSpace(student.Email))
{
errors.Add(nameof(student.Email),
new string[] { "Student email is required" });
}
if (errors.Count > 0)
{
return Results.ValidationProblem(errors);
}
return await next(context);
}
}
}
3. Student Model
namespace MiddlewareAndFiltersDemoWithDotNet.Models
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
}
4. SchoolDbContext
using Microsoft.EntityFrameworkCore;
using MiddlewareAndFiltersDemoWithDotNet.Models;
namespace MiddlewareAndFiltersDemoWithDotNet.Data
{
public class SchoolDbContext : DbContext
{
public DbSet<Student> Student { get; set; }
public SchoolDbContext(
DbContextOptions<SchoolDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
5. Program.cs File
The Program.cs file configures:
- Dependency Injection
- Entity Framework Core
- Middleware Pipeline
- Minimal APIs
- Endpoint Filters
Program.cs
using Microsoft.EntityFrameworkCore;
using MiddlewareAndFiltersDemoWithDotNet.Data;
using MiddlewareAndFiltersDemoWithDotNet.EndpointFilters;
using MiddlewareAndFiltersDemoWithDotNet.Middlewares;
using MiddlewareAndFiltersDemoWithDotNet.Models;
namespace MiddlewareAndFiltersDemoWithDotNet
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddDbContext<SchoolDbContext>(
options => options.UseSqlServer(
builder.Configuration.GetConnectionString("SchoolConn")));
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseMiddleware<RequestLoggingMiddleware>();
app.MapPost("/students",
(Student student, SchoolDbContext schoolDbContext) =>
{
schoolDbContext.Student.Add(student);
schoolDbContext.SaveChanges();
return Results.Created(
string.Format("/students/{0}", student.ID),
student);
}).AddEndpointFilter<StudentValidationEndpointFilter>();
app.MapGet("/students",
(SchoolDbContext schoolDbContext) =>
{
return Results.Ok(
schoolDbContext.Student.ToList());
});
app.MapGet("/students/{id:int}",
(int id, SchoolDbContext schoolDbContext) =>
{
var student = schoolDbContext.Student
.Where(x => x.ID == id)
.FirstOrDefault();
if (student != null)
{
return Results.Ok(student);
}
else
{
return Results.NotFound();
}
});
app.Run();
}
}
}
6. appsettings.json File
Add the SQL Server connection string inside the
appsettings.json file.
"ConnectionStrings": {
"SchoolConn": "Server=localhost;Initial Catalog=MyMWEF;Integrated Security=True;TrustServerCertificate=True;"
}
Entity Framework Core Migration
Add Migration
Add-Migration InitialCreate
Update Database
Update-Database
Add Student API Example
POST /students
Request Body
{
"name": "John Smith",
"email": "john@example.com"
}
Successful Response
{
"id": 1,
"name": "John Smith",
"email": "john@example.com"
}
Validation Error Example
{
"errors": {
"Name": [
"Student name is required"
],
"Email": [
"Student email is required"
]
}
}
Get All Students API Example
GET /students
Response
[
{
"id": 1,
"name": "John Smith",
"email": "john@example.com"
}
]
Get Student By ID API Example
GET /students/1
Response
{
"id": 1,
"name": "John Smith",
"email": "john@example.com"
}
Middleware vs Endpoint Filter
| Feature | Middleware | Endpoint Filter |
|---|---|---|
| Scope | Global | Endpoint Specific |
| Access to Endpoint Arguments | No | Yes |
| Best Use Case | Logging, Authentication | Validation, Endpoint Logic |
| Applied Using | UseMiddleware() | AddEndpointFilter() |
Conclusion
ASP.NET Core Minimal APIs provide a clean and modern approach for building REST APIs with minimal code.
By combining:
- Custom Middleware
- Endpoint Filters
- Entity Framework Core
- Dependency Injection
developers can build scalable, maintainable, and production-ready APIs efficiently.
In this article, we created:
- RequestLoggingMiddleware for request logging
- StudentValidationEndpointFilter for validation
- Student CRUD Minimal APIs
- SQL Server integration using Entity Framework Core