A Minimalist introduction to the Minimal API in .NET 6
Minimal API is the extremely simple way to write HTTP API with minimum dependencies. Its normal controller based API minus all its ceremonies.
The Minimalist get call is
app.MapGet("/", () => "Hello World!");
The call specifies a route (e.g., "/") and a callback that will be executed once a request matching the route and verb is received.
Now, Let’s see how the code will look like using Minimal APIs in .NET 6
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
You can see the Program.cs file in your ASP.NET Core project, containing the hello world API.
In comparison to the previous version of controller-based APIs, how minimal is it? What is missing?
- Startup.cs
- Global Using Statements
- Controller Classes
Instead of a Startup.cs class with places to set up services and middleware, it's all done in this very simple top-level program in Program.cs
Routing
Minimal API mapping patterns are a lot like pattern matching in MVC controllers.
Get call for route “/api/users”
app.MapGet("/api/users", () => new User()
{
Id = 1,
Name = "user”
});
Get call for route “/api/users” with parameters
app.MapGet("/api/users/{id:int}", (int id) => new User()
{
Id = id,
Name = "user " + id
});
Registering Services
In the Minimal api we can use the builder object to access the services.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<UserDBContext>();
builder.Services.AddTransient<IUserRepo, UserRepo>();
We can use the Services object on the application builder to add any services we need.
To use these services add them to the lambda expression parameter .
app.MapGet("/api/users", async (IUserRepo userRepo) =>
{
return await userRepo.GetUsersAsync();
});
It’s unlike controller based API where dependencies are injected at class level , in Minimal API dependencies are injected into the lambda expression.
How about other HTTP Verbs ?
There are methods for the different types of verbs. These include:
- MapGet
- MapPost
- MapPut
- MapDelete
app.MapPost("/users", async (User model, IUserRepo userRepo) =>
{
//..
});
app.MapPut("/users/{id}", async (int id, User model, IUserRepo userRepo) =>
{
});
app.MapMethods("/user", new[] { "PATCH" },
async (IUserRepo userRepo) => { });
How about Status Codes ?
We need a way of controlling what status code to return.These are handled with the Results static class.
app.MapGet("/api/users", async (IUserRepo userRepo) =>
{
return Results.Ok(await userRepo.GetUsersAsync());
});
Securing the API
Even though Minimal API works with Authorization and Authentication middleware, we need to specify access control at the API level. To require authorization
app.MapGet("/api/users", async (IUserRepo userRepo) =>
{
return Results.Ok(await userRepo.GetUsersAsync());
}).RequireAuthorization();
To allow anonymous users
app.MapGet("/api/users", async (IUserRepo userRepo) =>
{
return Results.Ok(await userRepo.GetUsersAsync());
}).AllowAnonymous();
Minimal APIs are a good starting point for creating API’s. When the project matures and becomes more complex we may have to move towards controller-based APIs.