Minimal API in .NET 8: A Simplfied Approach to Build Web APIs

Web API

In the quest for a more streamlined initiation into ASP.NET Core, Minimal APIs made their debut in .NET 6. Before this release, setting up a basic API involved at least three classes — Program.cs, Startup.cs, and an API controller — along with various conventions to comprehend. The introduction of Minimal APIs, coupled with WebApplicationBuilder, served as a remedy to simplify this process.

Advantages of Minimal APIs

  • Simplicity and Conciseness
  • Ease of Use
  • Lightweight Footprint
  • Quick Startup Time
  • Improved Performance
  • Focused on HTTP APIs
  • Reduced Configuration Overhead
  • Integration with ASP.NET Core

Limitation of Minimal APIs

  • Reduced Flexibility: Minimal APIs are designed to be lightweight, which can be limiting in terms of flexibility compared to the full MVC framework. This might be a disadvantage for complex applications with intricate requirements.
  • Limited Features: Minimal APIs, as the name suggests, provide a minimalistic set of features. If your application requires advanced features or extensive customization, you might find that the Minimal API approach doesn’t offer all the tools and capabilities you need.
  • Learning Curve: While Minimal APIs are intended to simplify development, they may have a learning curve for developers who are more accustomed to the traditional MVC approach. It might take time for developers to adjust to the new conventions and patterns.
  • Not Suitable for All Scenarios: Minimal APIs are best suited for lightweight scenarios, microservices, or simple applications. For larger and more complex projects, traditional MVC might be a more appropriate choice.

With minimal APIs, a simple HelloWorld solution looks something like this.

var builder = new WebApplication.CreateBuilder(args);
WebApplication app = builder.Build();

app.MapGet("/", () => "Hello world!");
app.Run();

Getting Started

  • Open Visual Studio and select the ASP.NET Core Web API.
    ASP.NET Core Web API
  • Provide a name and a location for your project.
    Configure new project
  • Select the framework.
  • Check the “Configure for HTTPS” and “Enable OpenAPI support” options.
  • Keep “Use controllers” checkbox unchecked.
  • Click the “Create” button.
    Additional information

Within this segment, we will delve into the Program.cs file, where the various components of our Minimal API converge. This file orchestrates the setup of services and the definition of endpoints.

using Microsoft.AspNetCore.Http.HttpResults;
using MinimalApi;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<IBookService, BookService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();


// Hello Word
app.MapGet("/", () => "Hello, World!");

// Example 1: Get all books
app.MapGet("/books", (IBookService bookService) =>
    TypedResults.Ok(bookService.GetBooks()))
    .WithName("GetBooks");

// Example 2: Get a specific book by ID
app.MapGet("/books/{id}", Results<Ok<Book>, NotFound> (IBookService bookService, int id) =>
{
    var book = bookService.GetBook(id);
    return book is { } ? TypedResults.Ok(book) : TypedResults.NotFound();
}).WithName("GetBookById");

// Example 3: Add a new book
app.MapPost("/books", (IBookService bookService, Book newBook) =>
{
    bookService.AddBook(newBook);
    return TypedResults.Created($"/books/{newBook.Id}", newBook);
}).WithName("AddBook");

// Example 4: Update an existing book
app.MapPut("/books/{id}", (IBookService bookService, int id, Book updatedBook) =>
{
    bookService.UpdateBook(id, updatedBook);
    return TypedResults.Ok();
}).WithName("UpdateBook");

// Example 5: Delete a book by ID
app.MapDelete("/books/{id}", (IBookService bookService, int id) =>
{
    bookService.DeleteBook(id);
    return TypedResults.NoContent();
}).WithName("DeleteBook");

app.Run();

The below code provides a BookService class for managing a collection of books, and the IBookService interface defines the contract for interacting with this service. It’s a basic example of a service that can perform CRUD operations on a collection of books.

namespace MinimalApi
{
    public interface IBookService
    {
        List<Book> GetBooks();

        Book GetBook(int id);

        void AddBook(Book book);

        void UpdateBook(int id, Book updatedBook);

        void DeleteBook(int id);
    }

    public class BookService : IBookService
    {
        private readonly List<Book> _books;

        public BookService()
        {
            _books = new List<Book>
            {
               new Book
               {
                   Id = 1,
                   Title = "Clean Code: A Handbook of Agile Software Craftsmanship",
                   Author = "Robert C. Martin"
               },
                new Book
                {
                    Id = 2,
                    Title = "Design Patterns: Elements of Reusable Object-Oriented Software",
                    Author = "Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides"
                },
                new Book
                {
                    Id = 3,
                    Title = "Refactoring: Improving the Design of Existing Code",
                    Author = "Martin Fowler"
                },
                new Book
                {
                    Id = 4,
                    Title = "Code Complete: A Practical Handbook of Software Construction",
                    Author = "Steve McConnell"
                }
            };
        }

        public List<Book> GetBooks()
        {
            return _books;
        }

        public Book GetBook(int id)
        {
            return _books.FirstOrDefault(x => x.Id == id);
        }

        public void AddBook(Book book)
        {
            _books.Add(book);
        }

        public void UpdateBook(int id, Book updatedBook)
        {
            var existingBook = _books.FirstOrDefault(x => x.Id == id);
            if (existingBook != null)
            {
                existingBook.Title = updatedBook.Title;
                existingBook.Author = updatedBook.Author;
            }
        }

        public void DeleteBook(int id)
        {
            var bookToRemove = _books.FirstOrDefault(x => x.Id == id);
            if (bookToRemove != null)
            {
                _books.Remove(bookToRemove);
            }
        }
    }

    public class Book
    {
        public int Id { get; set; }

        public string? Title { get; set; }

        public string? Author { get; set; }
    }
}

Topics to be covered in upcoming articles

  • API Rate Limiting
  • Error Handling
  • Authentication and Authorization
  • Caching
  • Request and Response Compression

The source code is available on the following repository: https://github.com/alibenchaabene/MinimalApi

Thank you for reading, please let me know your questions, thoughts, or feedback in the comments section. I appreciate your feedback and encouragement.

Happy Documenting!