Introduction to minimal APIs
In the previous section, Creating a simple web API project, we created a simple web API project using the dotnet new webapi -n MyFirstApi -controllers
command. The -controllers
option (or --use-controllers
) indicates that the project will use controller-based routing. Alternatively, the -minimal
or --use-minimal-apis
option can be used to create a project that uses minimal APIs. In this section, we will introduce minimal APIs.
Minimal APIs is a new feature introduced in ASP.NET Core 6.0. It is a new way to create APIs without using controllers. Minimal APIs are designed to be simple and lightweight with minimal dependencies. They are a good choice for small projects or prototypes, and also for projects that do not need the full features of controllers.
To create a minimal API project, we can use the following command:
dotnet new webapi -n
MinimalApiDemo -minimal
There is no Controllers
folder in the project. Instead, you can find the following code in the Program.cs
file:
app.MapGet("/weatherforecast", () => { var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast ( DateOnly.FromDateTime(DateTime.Now.AddDays(index)), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)] )) .ToArray(); return forecast; }) .WithName("GetWeatherForecast") .WithOpenApi();
The preceding code uses the MapGet()
method to map the GET
request to the /weatherforecast
endpoint. The MapGet()
method is an extension method of the IEndpointRouteBuilder
interface. This interface is used to configure the endpoints in the application. Its extension method, MapGet()
, returns an IEndpointConventionBuilder
interface that allows us to use fluent APIs to configure the endpoint by using other extension methods, such as WithName()
and WithOpenApi()
. The WithName()
method is used to set the name of the endpoint. The WithOpenApi()
method is used to generate an OpenAPI document for the endpoint.
Creating a simple endpoint
Let us create a new /posts
endpoint that supports CRUD operations. First, add the following code to the end of the Program.cs
file to define a Post
class:
public class Post { public int Id { get; set; } public string Title { get; set; } = string.Empty; public string Content { get; set; } = string.Empty; }
Add the following code to the Program.cs
file:
var list = new List<Post>() { new() { Id = 1, Title = "First Post", Content = "Hello World" }, new() { Id = 2, Title = "Second Post", Content = "Hello Again" }, new() { Id = 3, Title = "Third Post", Content = "Goodbye World" }, }; app.MapGet("/posts", () => list).WithName("GetPosts").WithOpenApi().WithTags("Posts"); app.MapPost("/posts", (Post post) => { list.Add(post); return Results.Created($"/posts/{post.Id}", post); }).WithName("CreatePost").WithOpenApi().WithTags("Posts"); app.MapGet("/posts/{id}", (int id) => { var post = list.FirstOrDefault(p => p.Id == id); return post == null ? Results.NotFound() : Results.Ok(post); }).WithName("GetPost").WithOpenApi().WithTags("Posts"); app.MapPut("/posts/{id}", (int id, Post post) => { var index = list.FindIndex(p => p.Id == id); if (index == -1) { return Results.NotFound(); } list[index] = post; return Results.Ok(post); }).WithName("UpdatePost").WithOpenApi().WithTags("Posts"); app.MapDelete("/posts/{id}", (int id) => { var post = list.FirstOrDefault(p => p.Id == id); if (post == null) { return Results.NotFound(); } list.Remove(post); return Results.Ok(); }).WithName("DeletePost").WithOpenApi().WithTags("Posts");
The preceding code defines five endpoints:
GET /posts
: Get all postsPOST /posts
: Create a new postGET /posts/{id}
: Get a post by IDPUT /posts/{id}
: Update a post by IDDELETE /posts/{id}
: Delete a post by ID
We use the WithTags
extension method to group these endpoints into a tag named Posts
. In this example, a list is used to store the posts. In a real-world application, we should use a database to store the data.
Using DI in minimal APIs
Minimal APIs support DI as well. You can find the IPostService
interface and its PostService
implementation in the Services
folder. Here is an example of using DI in minimal APIs:
app.MapGet("/posts", async (IPostService postService) => { var posts = await postService.GetPostsAsync(); return posts; }).WithName("GetPosts").WithOpenApi().WithTags("Posts"); app.MapGet("/posts/{id}", async (IPostService postService, int id) => { var post = await postService.GetPostAsync(id); return post == null ? Results.NotFound() : Results.Ok(post); }).WithName("GetPost").WithOpenApi().WithTags("Posts"); app.MapPost("/posts", async (IPostService postService, Post post) => { var createdPost = await postService.CreatePostAsync(post); return Results.Created($"/posts/{createdPost.Id}", createdPost); }).WithName("CreatePost").WithOpenApi().WithTags("Posts"); app.MapPut("/posts/{id}", async (IPostService postService, int id, Post post) => { try { var updatedPost = await postService.UpdatePostAsync(id, post); return Results.Ok(updatedPost); } catch (KeyNotFoundException) { return Results.NotFound(); } }).WithName("UpdatePost").WithOpenApi().WithTags("Posts"); app.MapDelete("/posts/{id}", async (IPostService postService, int id) => { try { await postService.DeletePostAsync(id); return Results.NoContent(); } catch (KeyNotFoundException) { return Results.NotFound(); } }).WithName("DeletePost").WithOpenApi().WithTags("Posts");
In the preceding code, the IPostService
interface is used as a parameter of the action method. The DI container will inject the correct implementation into the action method. You can run the project and test the endpoints. It should have the same behavior as the controller-based project.
What is the difference between minimal APIs and controller-based APIs?
Minimal APIs are simpler than controller-based APIs, allowing us to map endpoints to methods directly. This makes minimal APIs a good choice for quickly creating simple APIs or demo projects. However, minimal APIs do not support the full range of features that controllers provide, such as model binding, model validation, and so on. These features may be added in the future. Therefore, we will mainly use controller-based APIs and not discuss minimal APIs in detail in this book. If you want to learn more about minimal APIs, please refer to the official documentation at https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis.