# How To Structure Minimal APIs

> Minimal APIs were introduced to remove some of the ceremony of creating traditional APIs with controllers. I see one big issue with Minimal APIs: the lack of clear guidance around how to structure applications built with them. In this newsletter, I want to offer a few solutions for that problem.

Published: 2022-12-10. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/how-to-structure-minimal-apis

To keep **Minimal APIs** maintainable, group endpoints by feature instead of defining them all in one file.
You can write an extension method on `IEndpointRouteBuilder` for each feature, or use a library like **Carter** and its module concept.
Either way, related endpoints stay together as the API grows in complexity.

In this week's newsletter we are going to explore [**Minimal APIs**](https://milanjovanovic.tech/blog/minimal-apis-dotnet),
which were introduced in **.NET 6**.

**Minimal APIs** were introduced to remove some of the ceremony
of creating **traditional APIs with controllers**.
To define an endpoint, you can use the new extension
methods, such as `MapGet` to define a **GET** endpoint.

I see one big issue with **Minimal APIs**, and that is the lack
of clear guidance around how to structure applications
built with **Minimal APIs**.

In this newsletter, I want to offer a few solutions for that problem.

Let's dive in.

## How To Create Minimal APIs?

Let's define a simple **Minimal API** application with two endpoints.
We're going to create one `GET` endpoint for getting a list of products.
And one `POST` endpoint for saving a product to the database.

We're using the powerful **DI** feature that allows us to inject services
as expression arguments, which you can see in the two expressions below
where we are injecting the `AppDbContext`.

```csharp
var builder = WebApplication.CreateBuilder(args);

// Configure EF and other services...

var app = builder.Build();

app.MapGet("/products", async (AppDbContext dbContext) =>
{
    return Results.Ok(await dbContext.Products.ToListAsync());
});

app.MapPost("/products", async (Product product, AppDbContext dbContext) =>
{
    dbContext.Products.Add(product);

    await dbContext.SaveChangesAsync();

    return Results.Ok(product);
});

app.Run();
```

And with this we have a functioning **Minimal API** that we can develop further
as we continue to add more endpoints.

## The Problem With Maintaining Minimal APIs

There is one potential problem with structuring our **Minimal APIs** like
in the previous example. If we keep adding the **Minimal API** endpoints
in the same file, our API will become hard to maintain as it grows
in complexity. How can we solve the maintance problem with **Minimal APIs**?

One solution can be to use extension methods to encapsulate the
definiton of the **Minimal API** endpoints.

Here's an example of that:

```csharp
public static class ProductsModule
{
    public static void RegisterProductsEndpoints(this IEndpointRouteBuilder  endpoints)
    {
        endpoints.MapGet("/products", async (AppDbContext dbContext) =>
        {
            return Results.Ok(await dbContext.Products.ToListAsync());
        });

        endpoints.MapPost("/products", async (Product product, AppDbContext dbContext) =>
        {
            dbContext.Products.Add(product);

            await dbContext.SaveChangesAsync();

            return Results.Ok(product);
        });
    }
}
```

And then inside of `Program` we need to register the endpoints:

```csharp
app.RegisterProductsEndpoints();
```

You can see that this simplifies our **Minimal API** definition,
and we also have our endpoints grouped by feature in one place.
I think this improve the maintainability of **Minimal APIs**,
but it comes at a cost. And that cost is having to define
extension methods for each group of endpoints you want to encapsulate,
and then you have to remember to call that extensions method in `Program`.

Can we do better?

## Structuring Minimal API Projects With Modules

I want to introduce you to an interesting open source library
called [Carter](https://github.com/CarterCommunity/Carter),
which has a concept of modules that we can use to group endpoints.

Here's how we can define our `ProductsModule` with **Carter**:

```csharp
public class ProductsModule : ICarterModule
{
    public void AddRoutes(IEndpointRouteBuilder app)
    {
        app.MapGet("/products", async (AppDbContext dbContext) =>
        {
            return Results.Ok(await dbContext.Products.ToListAsync());
        });

        app.MapPost("/products", async (Product product, AppDbContext dbContext) =>
        {
            dbContext.Products.Add(product);

            await dbContext.SaveChangesAsync();

            return Results.Ok(product);
        });
    }
}
```

This takes care of configuring our **Minimal API** endpoints, but we still
need to tell the framework to use these endpoints. We have to slightly
modify the `Program` to register the required **Carter** services by
calling `AddCarter`, and also map our endpoints by calling `MapCarter`.

```csharp
var builder = WebApplication.CreateBuilder(args);

// Configure EF and other services...

builder.Services.AddCarter();

var app = builder.Build();

app.MapCarter();

app.Run();
```

When we want to define additional **Minimal API** endpoints we just need to
implement a new `ICarterModule`, and register our endpoints. **Carter** will
automatically take care of registering the new endpoints after that.

## Would I Use Minimal APIs In a Real Project?

I think **Minimal APIs** have evolved nicely since they were first introduced
in **.NET 6**. I would be careful with using them in very large applications,
but I'm definitely going to explore options for using them on smaller projects.

A good use case can be for building a [**microservice**](https://milanjovanovic.tech/blog/microservices-dotnet-getting-started) that has a limited
number of endpoints.

---

## Frequently asked questions

### What are Minimal APIs in .NET?

Minimal APIs, introduced in .NET 6, remove some of the ceremony of creating traditional APIs with controllers. You define endpoints with extension methods such as MapGet and MapPost directly on the application, and you can inject services as arguments of the endpoint expression.

### What is the problem with putting all Minimal API endpoints in one file?

If you keep adding endpoints in the same file, the API becomes hard to maintain as it grows in complexity. Grouping endpoints by feature, with extension methods or a library like Carter, keeps related endpoints together and improves maintainability.

### How do you organize Minimal API endpoints with extension methods?

Create a static class per feature with an extension method on IEndpointRouteBuilder that registers that feature's endpoints, then call it in Program. The cost is defining an extension method for each group of endpoints and remembering to call it during startup.

### What is Carter and how does it help structure Minimal APIs?

Carter is an open source library with a module concept for grouping endpoints. You implement ICarterModule and define routes in AddRoutes, then call AddCarter and MapCarter in Program. Carter automatically registers the endpoints of every new module you add.

### Should you use Minimal APIs in a real project?

I would be careful with Minimal APIs in very large applications, but they are worth exploring on smaller projects. A good use case is a microservice with a limited number of endpoints.
