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();

Program.PNG

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.