Course Content
About Minimal APIs
0/1
Naming Conventions
0/1
Implementing the Result Pattern in Minimal APIs
0/2
Minimal APIs in ASP.NET Core

In the previous modules, we introduced many great improvements to our application and now we’ll explore how to better structure and manage our minimal endpoints. So far, we’ve had all of our endpoints in the Program class – this is fine for many small applications but as our API grows, we need to do something or our code might get messy and hard to maintain.

In this module, we’ll explore how to structure our API better and remove the clutter from the Program class while introducing better maintainability to our application.

Extension methods are a great tool in .NET that allows us to add new functionality to existing types easily. We’ll use this approach to restructure our two existing endpoints.

Let’s start by navigating to our main project and creating a folder called Endpoints. Then inside this folder, let’s create a new class and call it ProjectEndpoints:

public static class ProjectEndpoints
{
    public static void RegisterProjectEndpoints(
        this IEndpointRouteBuilder routeBuilder)
    {
        
    }
}

We create the ProjectEndpoints class and mark it as static. Then, inside it, we add the RegisterProjectEndpoints() method. It is also static and returns void. It is going to be an extension method on the IEndpointRouteBuilder interface, so we pass this as a parameter preceded by the this keyword. The keyword is vital for the extension method to work properly.

We extend the IEndpointRouteBuilder interface as it is used to define the contract for route building in ASP.NET Core. Furthermore, the WebApplication class implements it and we’ll be able to use our extension method directly on our app variable in the Program class.

Now, let’s hop to the Program class and cut the first two project endpoints from there.

After doing that, let’s get back to the ProjectEndpoints class:

public static class ProjectEndpoints
{
    public static void RegisterProjectEndpoints(
        this IEndpointRouteBuilder routeBuilder)
    {
        routeBuilder.MapGet("api/projects", async (
            [FromServices] IServiceManager serviceManager,
            CancellationToken cancellationToken) =>
        {
            var projects = await serviceManager.ProjectService
                    .GetAllProjectsAsync(cancellationToken);

            return Results.Ok(projects);
        });

        routeBuilder.MapGet("api/projects/{id:guid}", async (
            [FromRoute] Guid id,
            [FromServices] IServiceManager serviceManager,
            CancellationToken cancellationToken) =>
        {
            var project = await serviceManager.ProjectService
                    .GetProjectAsync(
                        id,
                        trackChanges: false,
                        cancellationToken);

            return Results.Ok(project);
        });
    }
}

Here, let’s paste both endpoints inside the RegisterProjectEndpoints() method. The only change we need to make for them to work is to rename app to routeBuilder.

Now, there is one final thing left to do in the Program class:

app.UseHttpsRedirection();
app.UseExceptionHandler();

app.RegisterProjectEndpoints();

We call the RegisterProjectEndpoints() on our WebApplication instance after the UseHttpsRedirection() and UseExceptionHandler() methods – exactly where our two endpoints used to be. With this approach, we’ve replaced over 20 lines of code with a single one!

Let’s run our API now and try to retrieve all projects via Postman by sending a GET request:

curl --location 'https://localhost:5001/api/projects'

As expected, we get the same result we did before – we still have the same endpoints, they are just structured differently.

So, as we can see, extension methods are a great way to maintain minimal API endpoints more elegantly.

Next, we’ll explore how reflection can help us achieve the same result.

0% Complete