MinimalApiBuilder 5.0.0-beta.4

This is a prerelease version of MinimalApiBuilder.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package MinimalApiBuilder --version 5.0.0-beta.4
NuGet\Install-Package MinimalApiBuilder -Version 5.0.0-beta.4
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MinimalApiBuilder" Version="5.0.0-beta.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MinimalApiBuilder --version 5.0.0-beta.4
#r "nuget: MinimalApiBuilder, 5.0.0-beta.4"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MinimalApiBuilder as a Cake Addin
#addin nuget:?package=MinimalApiBuilder&version=5.0.0-beta.4&prerelease

// Install MinimalApiBuilder as a Cake Tool
#tool nuget:?package=MinimalApiBuilder&version=5.0.0-beta.4&prerelease

MinimalApiBuilder

nuget

Reflectionless, source-generated, thin abstraction layer over the ASP.NET Core Minimal APIs interface.

How to Use

Based on the Vertical Slice Architecture with Feature folder. There is one class for every API endpoint. A basic example looks like the following:

using Microsoft.AspNetCore.Mvc;
using MinimalApiBuilder;

public partial class BasicEndpoint : MinimalApiBuilderEndpoint
{
    public static string Handle()
    {
        return "Hello, World!";
    }
}

The endpoint class must be partial, inherit from MinimalApiBuilderEndpoint, and have a static Handle or HandleAsync method. The endpoint is mapped through the typical IEndpointRouteBuilder Map<Verb> extension methods:

app.MapGet("/hello", BasicEndpoint.Handle);

This library depends on FluentValidation >= 11. An endpoint can have a validated request object:

public struct BasicRequest
{
    public required string Name { get; init; }
}

public partial class BasicRequestEndpoint : MinimalApiBuilderEndpoint
{
    public static string Handle([AsParameters] BasicRequest request)
    {
        return $"Hello, {request.Name}!";
    }
}

public class BasicRequestValidator : AbstractValidator<BasicRequest>
{
    public BasicRequestValidator()
    {
        RuleFor(static request => request.Name).MinimumLength(2);
    }
}

The incremental generator will generate code to validate the request object before the handler is called and return a ValidationProblem validation error result if the validation fails. To wire up the validation filters and to support the Request Delegate Generator, the Map methods need to be wrapped by the ConfigureEndpoints.Configure helper, which expects a comma-separated list of RouteHandlerBuilder:

using static MinimalApiBuilder.ConfigureEndpoints;

Configure(app.MapGet("/hello/{name}", BasicRequestEndpoint.Handle));

Validation in custom binding scenarios is also supported. For example, adapting the Microsoft BindAsync sample:

<details> <summary>Show example</summary>

public record PagingData(string? SortBy, SortDirection SortDirection, int CurrentPage)
{
    private const string SortByKey = "sortby";
    private const string SortDirectionKey = "sortdir";
    private const string PageKey = "page";

    public static ValueTask<PagingData?> BindAsync(HttpContext httpContext)
    {
        ProductsEndpoint endpoint =
            httpContext.RequestServices.GetRequiredService<ProductsEndpoint>();

        SortDirection sortDirection = default;
        int page = default;

        if (httpContext.Request.Query.TryGetValue(SortDirectionKey,
            out StringValues sortDirectionValues))
        {
            if (!Enum.TryParse(sortDirectionValues, ignoreCase: true, out sortDirection))
            {
                endpoint.AddValidationError(SortDirectionKey,
                    "Invalid sort direction. Valid values are 'default', 'asc', or 'desc'.");
            }
        }
        else
        {
            endpoint.AddValidationError(SortDirectionKey, "Missing sort direction.");
        }

        if (httpContext.Request.Query.TryGetValue(PageKey, out StringValues pageValues))
        {
            if (!int.TryParse(pageValues, out page))
            {
                endpoint.AddValidationError(PageKey, "Invalid page number.");
            }
        }
        else
        {
            endpoint.AddValidationError(PageKey, "Missing page number.");
        }

        if (endpoint.HasValidationError)
        {
            return ValueTask.FromResult<PagingData?>(null);
        }

        PagingData result = new(httpContext.Request.Query[SortByKey], sortDirection, page);

        return ValueTask.FromResult<PagingData?>(result);
    }
}

public enum SortDirection
{
    Default,
    Asc,
    Desc
}

public partial class ProductsEndpoint : MinimalApiBuilderEndpoint
{
    public static string Handle(PagingData pageData)
    {
        return pageData.ToString();
    }
}
Configure(app.MapGet("/products", ProductsEndpoint.Handle));

</details>

Unfortunately, TryParse cannot be validated this way as there is no easy way to access the IServiceProvider right now. To not short-circuit execution by throwing an exception when returning null from BindAsync, ThrowOnBadRequest needs to be disabled:

builder.Services.Configure<RouteHandlerOptions>(static options =>
{
    options.ThrowOnBadRequest = false;
});

Endpoints and validators need to be registered with dependency injection. The following method adds them:

builder.Services.AddMinimalApiBuilderEndpoints();

Configuration

Users can add configuration through entries in .editorconfig or with MSBuild properties. The following options are available, with configuration snippets showing the default values:

minimalapibuilder_assign_name_to_endpoint (true | false)

If true, the generator will add a unique public const string Name field to the endpoint classes and call the WithName extension method when mapping them.

minimalapibuilder_assign_name_to_endpoint = false
<PropertyGroup>
  <minimalapibuilder_assign_name_to_endpoint>false</minimalapibuilder_assign_name_to_endpoint>
</PropertyGroup>

minimalapibuilder_validation_problem_type (string)

The type of the ValidationProblem validation error result.

minimalapibuilder_validation_problem_type = "https://tools.ietf.org/html/rfc9110#section-15.5.1"
<PropertyGroup>
  <minimalapibuilder_validation_problem_type>https://tools.ietf.org/html/rfc9110#section-15.5.1</minimalapibuilder_validation_problem_type>
</PropertyGroup>

minimalapibuilder_validation_problem_title (string)

The title of the ValidationProblem validation error result.

minimalapibuilder_validation_problem_title = "One or more validation errors occurred."
<PropertyGroup>
  <minimalapibuilder_validation_problem_title>One or more validation errors occurred.</minimalapibuilder_validation_problem_title>
</PropertyGroup>

minimalapibuilder_model_binding_problem_type (string)

The type of the ValidationProblem model binding error result.

minimalapibuilder_model_binding_problem_type = "https://tools.ietf.org/html/rfc9110#section-15.5.1"
<PropertyGroup>
  <minimalapibuilder_model_binding_problem_type>https://tools.ietf.org/html/rfc9110#section-15.5.1</minimalapibuilder_model_binding_problem_type>
</PropertyGroup>

minimalapibuilder_model_binding_problem_title (string)

The title of the ValidationProblem model binding error result.

minimalapibuilder_model_binding_problem_title = "One or more model binding errors occurred."
<PropertyGroup>
  <minimalapibuilder_model_binding_problem_title>One or more model binding errors occurred.</minimalapibuilder_model_binding_problem_title>
</PropertyGroup>
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
5.0.0-beta.10 81 1/25/2024
5.0.0-beta.9 51 1/22/2024
5.0.0-beta.8 85 1/3/2024
5.0.0-beta.7 78 12/29/2023
5.0.0-beta.6 63 12/18/2023
5.0.0-beta.5 75 12/15/2023
5.0.0-beta.4 89 11/27/2023
5.0.0-beta.3 75 11/23/2023
5.0.0-beta.2 60 11/23/2023
5.0.0-beta.1 89 11/21/2023
4.0.0 208 11/12/2023
3.1.0 83 11/8/2023
3.0.1 83 11/6/2023
3.0.0 150 11/6/2023
2.0.0 111 10/30/2023
1.4.0 103 10/27/2023
1.3.3 247 5/11/2023
1.3.2 118 5/8/2023
1.3.1 115 5/8/2023
1.3.0 115 5/8/2023
1.2.0 121 5/6/2023
1.1.0 125 5/1/2023
1.0.1 308 2/10/2023
1.0.0 326 1/5/2023
0.1.0-beta.12 94 1/5/2023
0.1.0-beta.11 88 1/5/2023
0.1.0-beta.10 83 1/5/2023
0.1.0-beta.9 96 1/5/2023
0.1.0-beta.8 97 1/5/2023
0.1.0-beta.7 93 1/4/2023
0.1.0-beta.6 95 1/4/2023
0.1.0-beta.5 87 1/4/2023
0.1.0-beta.4 92 1/4/2023
0.1.0-beta.3 91 1/4/2023
0.1.0-beta.2 92 12/31/2022
0.1.0-beta.1 96 12/30/2022