Book Image

Mastering Minimal APIs in ASP.NET Core

By : Andrea Tosato, Marco Minerva, Emanuele Bartolesi
Book Image

Mastering Minimal APIs in ASP.NET Core

By: Andrea Tosato, Marco Minerva, Emanuele Bartolesi

Overview of this book

The Minimal APIs feature, introduced in .NET 6, is the answer to code complexity and rising dependencies in creating even the simplest of APIs. Minimal APIs facilitate API development using compact code syntax and help you develop web APIs quickly. This practical guide explores Minimal APIs end-to-end and helps you take advantage of its features and benefits for your ASP.NET Core projects. The chapters in this book will help you speed up your development process by writing less code and maintaining fewer files using Minimal APIs. You’ll also learn how to enable Swagger for API documentation along with CORS and handle application errors. The book even promotes ideas to structure your code in a better way using the dependency injection library in .NET. Finally, you'll learn about performance and benchmarking improvements for your apps. By the end of this book, you’ll be able to fully leverage new features in .NET 6 for API development and explore how Minimal APIs are an evolution over classical web API development in ASP.NET Core.
Table of Contents (16 chapters)
1
Part 1: Introduction
5
Part 2: What’s New in .NET 6?
10
Part 3: Advanced Development and Microservices Concepts

Looking at the structure of the project

Whether you are using Visual Studio or Visual Studio Code, you should see the following code in the Program.cs file:

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", 
    "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
  var forecast = Enumerable.Range(1, 5).Select(index =>
      new WeatherForecast
      (
          DateTime.Now.AddDays(index),
          Random.Shared.Next(-20, 55),
          summaries[Random.Shared.Next(summaries.Length)]
      ))
      .ToArray();
      return forecast;
})
.WithName("GetWeatherForecast");
app.Run();
internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 
    0.5556);
}

First of all, with the minimal API approach, all of your code will be inside the Program.cs file. If you are a seasoned .NET developer, it’s easy to understand the preceding code, and you’ll find it similar to some of the things you’ve always used with the controller approach.

At the end of the day, it’s another way to write an API, but it’s based on ASP.NET Core.

However, if you are new to ASP.NET, this single file approach is easy to understand. It’s easy to understand how to extend the code in the template and add more features to this API.

Don’t forget that minimal means that it contains the minimum set of components needed to build an HTTP API but it doesn’t mean that the application you are going to build will be simple. It will require a good design like any other .NET application.

As a final point, the minimal API approach is not a replacement for the MVC approach. It’s just another way to write the same thing.

Let’s go back to the code.

Even the template of the minimal API uses the new approach of .NET 6 web applications: a top-level statement.

It means that the project has a Program.cs file only instead of using two files to configure an application.

If you don’t like this style of coding, you can convert your application to the old template for ASP.NET Core 3.x/5. This approach still continues to work in .NET as well.

Important note

We can find more information about the .NET 6 top-level statements template at https://docs.microsoft.com/dotnet/core/tutorials/top-level-templates.

By default, the new template includes support for the OpenAPI Specification and more specifically, Swagger.

Let’s say that we have our documentation and playground for the endpoints working out of the box without any additional configuration needed.

You can see the default configuration for Swagger in the following two lines of codes:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

Very often, you don’t want to expose Swagger and all the endpoints to the production or staging environments. The default template enables Swagger out of the box only in the development environment with the following lines of code:

if (app.Environment.IsDevelopment())
{
         app.UseSwagger();
         app.UseSwaggerUI();
}

If the application is running on the dev elopment environment, you must also include the Swagger documentation, but otherwise not.

Note

We’ll talk in detail about Swagger in Chapter 3, Working with Minimal APIs.

In these last few lines of code in the template, we are introducing another generic concept for .NET 6 web applications: environments.

Typically, when we develop a professional application, there are a lot of phases through which an application is developed, tested, and finally published to the end users.

By convention, these phases are regulated and called development, staging, and production. As developers, we might like to change the behavior of the application based on the current environment.

There are several ways to access this information but the typical way to retrieve the actual environment in modern .NET 6 applications is to use environment variables. You can access the environment variables directly from the app variable in the Program.cs file.

The following code block shows how to retrieve all the information about the environments directly from the startup point of the application:

if (app.Environment.IsDevelopment())
{
           // your code here
}
if (app.Environment.IsStaging())
{
           // your code here
}
if (app.Environment.IsProduction())
{
           // your code here
}

In many cases, you can define additional environments, and you can check your custom environment with the following code:

if (app.Environment.IsEnvironment("TestEnvironment"))
{
           // your code here
}

To define routes and handlers in minimal APIs, we use the MapGet, MapPost, MapPut, and MapDelete methods. If you are used to using HTTP verbs, you will have noticed that the verb Patch is not present, but you can define any set of verbs using MapMethods.

For instance, if you want to create a new endpoint to post some data to the API, you can write the following code:

app.MapPost("/weatherforecast", async (WeatherForecast 
    model, IWeatherService repo) =>
{
         // ...
});

As you can see in the short preceding code, it’s very easy to add a new endpoint with the new minimal API template.

It was more difficult previously, especially for a new developer, to code a new endpoint with binding parameters and use dependency injection.

Important note

We’ll talk in detail about routing in Chapter 2, Exploring Minimal APIs and Their Advantages, and about dependency injection in Chapter 4, Dependency Injection in a Minimal API Project.