Minimal API in ASP.NET Core
Minimal APIs were released at the same time as .NET 6, C# 10, and a number of performance improvements. But what exactly are they, and how do they work? This is what we plan to cover in this post to mark the release of .NET 7 and the announcement of new improvements.
What Is a Minimal API?
The minimal API concept is presented as an alternative to the ASP.NET Core Controller for defining an API with as few dependencies as possible. It appears to be Microsoft’s attempt to compete with the NodeJS APIs (via ExpressJS).
Let’s take a closer look at a standard NodeJS API:
The code above is a standard way of defining a GET Endpoint that returns the list of platforms supported by a NodeJS server. There is also a declaration of the port that the server is listening on (3000 in this case).
This API gives this answer:
Now let’s try to do the same thing with the minimal ASP.NET Core API.
Creating the First Endpoint
To create our first minimal API, we’ll use this command to set up an empty ASP.NET Core project:
Dotnet new web -n MyMinimalAPI
This will create a web project with the fewest dependencies and the following Program.cs:
When we run the application, the “Hello World!” message appears in our browser.
What’s going on in these four lines of code? Let’s dive in and find out.
The first thing you should notice is the absence of “using” at the start of the file. This is because the concept of global using was introduced in C# 10. This feature allows you to specify a “using” declaration that will be considered present in all the project files. The “ImplicitUsings” key in the csproj file enables this functionality by default.
Below is a list of the default global “usings” defined in the “template.” We can see the “Microsoft.AspNetCore.Builder” namespace where the MapGet() method is defined.
Here is the MapGet method, which has the following signatures:
They take a delegate as their third parameter, so we can pass any method, and the compiler will convert our delegate into a “RequestDelegate” if it can.
Lastly, “app.Run()” lets you launch the application.
This is what our API would look like in NodeJS:
The Urls property lets you declare the ports to listen on.
Each endpoint’s routing is declared explicitly. The endpoint route in the previous example was “/my-supported-platforms.” This route has no variables, but it can be modified as follows:
Above, we defined a new Endpoint that returns a specific platform when the platform identifier is passed.
The dependency manager now has a new feature that lets it know which types are registered and can be retrieved from its container. So, you no longer need to use an attribute to declare that a type comes from the dependency management container.
With a minimal API, we can inject our dependencies as follows:
Here, our Endpoint depends on two parameters, and ASP.NET is smart enough to know where to look for the dependencies. However, if you try to run the project after making this change, you will get the following error:
This error occurred because ASP.NET Core could not find at least one of the Endpoint dependencies. Here, “IHppClientFactory” is not registered in the dependency manager, so ASP.NET Core can’t find the factory in the request body.
To fix this error, add the missing type to your dependency manager as follows:
The AddHttpClient method will add “IHttpClientFactory” to the dependency manager, making it retrievable.
Declaring the Verbs
The minimal API exposes dedicated methods for POST, PUT and DELETE verbs as follows:
The signatures for these methods are the same as those for the “MapGet” method.
Minimal API Implementation
Let’s apply what we just learned to a specific scenario. We’re going to make a book management app with the CRUD (Create, Read, Update, Delete) features:
- Retrieve all books
- Retrieve book details
- Create a new book
- Update a book
- Delete a book
Model and Basic Use Case
For this example, we chose the following data model:
We’ll use “Entity Framework Core” with “Sqlite” to persist and manipulate our data. We install the following NuGet packages at the root of our project:
dotnet add package Microsoft.EntityFrameworkCore.Sqlite dotnet add package Microsoft.EntityFrameworkCore.Design
The first one is used to interact with our data, and the second one lets us initialize our database with the following code:
This code in Program.cs is responsible for initializing our database and the associated “context”:
Let’s create our first Endpoints, which will allow us to:
- Retrieve all books
- Retrieve a book’s details
As we’ve seen, the dependency manager finds the “dbContext” and injects it into our delegate.
You’ll notice that we use the methods of the “Results” class in the “Microsoft.AspNetCore.Http” namespace to return the result. The latter exposes a large number of HTTP response types. For more information, please visit the GitHub page for the class.
Create, Update, and Delete
Now that we know how to read data, let’s look at how to create, update, and delete data. This uses the same approach.
The update procedure is similar to the create procedure, except that you pass the identifier of the book to be modified.
Finally, delete is as follows:
Minimal API supports the OpenAPI specifications through Swashbuckle.
- Let’s install Swashbuckle in our project.
dotnet add package Swashbuckle.AspNetCore
- We then inject the services that Swagger needs to function.
- Next, we add the Swagger UI to the ASP.NET Core middleware.
- We compile and launch the project in the Swagger endpoint: /swagger/index.html.
All the Endpoints we created earlier are present. We can go one step further by adding more information to the Endpoint descriptions, as shown in the examples below:
.NET 6 has introduced extension methods that allow you to add more details to endpoint definitions:
- Produces: describes the type of resources returned by the endpoint and the response status
- WithName: unique Endpoint identifier
- WithTags: name of an Endpoint’s category
The Endpoints are grouped into the categories we defined earlier.
Minimal API: Key Takeaways
Minimal API is a new tool that helps developers create APIs quickly and without the full ASP.NET Core MVC or Web API stack.
We looked at how easy it is to implement minimal APIs in a web project using a specific CRUD use scenario. Next, we saw how ASP.NET Core makes it easy to manage the Endpoint dependencies with little code because it knows where to find them.
You can find the source code for this article here.
We recommend reading the following documentation to help you learn more:
- Minimal APIs quick reference | Microsoft Learn
- Tutorial: Create a minimal web API with ASP.NET Core | Microsoft Learn
Read the other posts in this series for more information on the latest additions to.NET 7 :
- What’s New in C# 11?
- Regain Control of Cache Management With Output Caching and .NET 7
- New in ASP.NET Core 7: Rate Limiting Middleware