Nabs.Launchpad.Core.Apis 10.0.287

Prefix Reserved
dotnet add package Nabs.Launchpad.Core.Apis --version 10.0.287
                    
NuGet\Install-Package Nabs.Launchpad.Core.Apis -Version 10.0.287
                    
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="Nabs.Launchpad.Core.Apis" Version="10.0.287" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nabs.Launchpad.Core.Apis" Version="10.0.287" />
                    
Directory.Packages.props
<PackageReference Include="Nabs.Launchpad.Core.Apis" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nabs.Launchpad.Core.Apis --version 10.0.287
                    
#r "nuget: Nabs.Launchpad.Core.Apis, 10.0.287"
                    
#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.
#:package Nabs.Launchpad.Core.Apis@10.0.287
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nabs.Launchpad.Core.Apis&version=10.0.287
                    
Install as a Cake Addin
#tool nuget:?package=Nabs.Launchpad.Core.Apis&version=10.0.287
                    
Install as a Cake Tool

NuGet

Nabs.Launchpad.Core.Apis

Nabs.Launchpad.Core.Apis gives you granular endpoint abstractions for consistent ASP.NET Core API endpoints.

Installation

dotnet add package Nabs.Launchpad.Core.Apis

Optional MSBuild OpenAPI export + Kiota client generation:

dotnet add package Nabs.Launchpad.Core.Apis.OpenApi.Export

The Problem

// 1) Controllers accumulate many actions over time
public class ProductsController : ControllerBase
{
    [HttpGet("{id:guid}")] public IActionResult Get(Guid id) => Ok();
    [HttpPost] public IActionResult Create(ProductRequest request) => Ok();
    [HttpPut("{id:guid}")] public IActionResult Update(Guid id, ProductRequest request) => Ok();
}

// 2) Endpoint intent is harder to isolate by file
// 3) Growth increases merge conflicts and maintenance overhead

Features

  • Single-file endpoint abstraction through INabsEndpoint
  • Verb convenience bases (NabsGetEndpoint, NabsPostEndpoint, NabsPutEndpoint, NabsPatchEndpoint, NabsDeleteEndpoint, NabsHeadEndpoint, NabsOptionsEndpoint, NabsTraceEndpoint, NabsQueryEndpoint, NabsSelectEndpoint, NabsConnectEndpoint) — route + optional configure; verb is implied
  • Declarative endpoint base class through NabsEndpointBase when you need custom or multi-method options
  • Typed request/response endpoint variants for common API patterns
  • FluentValidation via options (RequestValidator / ResponseValidator) with ValidateRequestAsync as an escape hatch
  • Constructor injection support for discovered endpoint classes
  • Automatic endpoint registration through MapNabsEndpoints(...)
  • Deterministic endpoint discovery for predictable startup behavior
  • Optional host helpers (AddNabsApis / UseNabsApis) for OpenAPI + JWT bearer
  • Host OpenAPI self-export through TryExportOpenApiAndExitAsync("--export-openapi")
  • Optional shared controller base through NabsControllerBase

Preferred pattern

  1. Derive from a verb convenience base (NabsGetEndpoint<TResponse>, NabsPostEndpoint<TRequest, TResponse>, …).
  2. Pass route + optional configure (: base("/api/...", static o => { ... })). The HTTP verb is implied — do not restate NabsEndpointOptions.Get/Post/... on convenience bases. Those factories are for raw NabsEndpointBase only.
  3. Put metadata and validators on NabsEndpointOptions in the configure callback.
  4. Register with app.MapNabsEndpoints<Program>();
public sealed class GetProductEndpoint : NabsGetEndpoint<ProductResponse>
{
    public GetProductEndpoint()
        : base("/api/products/{id:guid}", static o =>
        {
            o.EndpointName = "GetProduct";
            o.Tags = ["Products"];
            o.Summary = "Get a product by id.";
        })
    {
    }

    protected override Task<ProductResponse> HandleAsync(CancellationToken cancellationToken)
        => Task.FromResult(new ProductResponse(Guid.NewGuid()));
}

public sealed class CreateProductValidator : AbstractValidator<CreateProductRequest>
{
    public CreateProductValidator()
    {
        RuleFor(x => x.Name).NotEmpty();
    }
}

public sealed class CreateProductEndpoint : NabsPostEndpoint<CreateProductRequest, CreateProductResponse>
{
    public CreateProductEndpoint()
        : base("/api/products", static o =>
        {
            o.EndpointName = "CreateProduct";
            o.Tags = ["Products"];
            o.RequestValidator = new CreateProductValidator();
        })
    {
    }

    protected override Task<CreateProductResponse> HandleAsync(
        CreateProductRequest request, CancellationToken cancellationToken)
        => Task.FromResult(new CreateProductResponse(Guid.NewGuid(), request.Name));
}

// Program.cs
app.MapNabsEndpoints<Program>();

Put endpoint metadata on NabsEndpointOptions. Do not rely on overriding EndpointName / Tags / Summary / Description on the base for new code. Those overrides remain for compatibility only.

Prefer FluentValidation via options. Set RequestValidator / ResponseValidator in the configure callback. Do not override ValidateRequestAsync for new code (escape hatch only). Request failures map to HTTP 400 ValidationProblem; response failures map to HTTP 500 Problem (errors extension).

You can still implement INabsEndpoint directly, or use NabsEndpointBase / NabsEndpointBase<TRequest, TResponse> with NabsNone when you need custom HTTP methods or multi-method options.

public sealed class SecureProductEndpoint : NabsEndpointBase
{
    private readonly IProductService _productService;

    public SecureProductEndpoint(IProductService productService)
        : base(NabsEndpointOptions.Get("/api/secure-products/{id:guid}", static o =>
        {
            o.RequireAuthorization = true;
        }))
    {
        _productService = productService;
    }

    protected override Task<IResult> HandleAsync(HttpContext httpContext, CancellationToken cancellationToken)
    {
        var id = httpContext.GetRouteValue("id");
        return Task.FromResult<IResult>(Results.Ok(_productService.GetById(id)));
    }
}

public sealed class ProcessOrderEndpoint : NabsEndpointBase<ProcessOrderRequest, NabsNone>
{
    public ProcessOrderEndpoint()
        : base("/api/orders/process", HttpMethod.Post)
    {
    }

    protected override Task<NabsNone> HandleAsync(ProcessOrderRequest request, CancellationToken cancellationToken)
    {
        return Task.FromResult(default(NabsNone));
    }
}

public sealed class ValidatedOrderEndpoint : NabsEndpointBase<CreateOrderRequest, CreateOrderResponse>
{
    public ValidatedOrderEndpoint()
        : base("/api/orders/validated", HttpMethod.Post)
    {
    }

    protected override Task<IDictionary<string, string[]>?> ValidateRequestAsync(CreateOrderRequest request, CancellationToken cancellationToken)
    {
        if (!string.IsNullOrWhiteSpace(request.CustomerName))
        {
            return Task.FromResult<IDictionary<string, string[]>?>(null);
        }

        IDictionary<string, string[]> errors = new Dictionary<string, string[]>
        {
            ["customerName"] = ["Customer name is required."]
        };

        return Task.FromResult<IDictionary<string, string[]>?>(errors);
    }

    protected override Task<CreateOrderResponse> HandleAsync(CreateOrderRequest request, CancellationToken cancellationToken)
    {
        return Task.FromResult(new CreateOrderResponse(Guid.NewGuid()));
    }
}

Controller-based APIs remain supported:

[ApiController]
[Route("api/[controller]")]
public sealed class ProductsController : NabsControllerBase
{
    [HttpGet("{id:guid}")]
    public IActionResult Get(Guid id) => Ok(new { id });
}

Optional host helpers

AddNabsApis / UseNabsApis are additive. Existing Launchpad hosts that already call AddServiceDefaults, AddOpenApi, or FeatureManagement can keep that setup and only call MapNabsEndpoints.

builder.Services.AddNabsApis(builder.Configuration);
// optional: builder.Services.AddNabsApis(builder.Configuration, o => { o.UseJwtBearerAuthentication = false; });

var app = builder.Build();
app.UseNabsApis();
app.MapNabsEndpoints<Program>();

if (await app.TryExportOpenApiAndExitAsync(args))
{
    return;
}

JWT bearer settings are read from Authentication:JwtBearer (Issuer, Audience, SigningKey) when authentication is enabled.

When both UseOpenApi and UseJwtBearerAuthentication are enabled (the default), AddNabsApis(builder.Configuration) registers an OpenAPI HTTP bearer JWT security scheme named Bearer and adds a document-level security requirement referencing that scheme.

If you explicitly opt out with UseJwtBearerAuthentication = false, the Bearer OpenAPI scheme is not added (while OpenAPI can still be enabled via UseOpenApi = true).

API contract

For Launchpad API hosts that use this package, the following is the shared contract.

OpenAPI is the source of truth

  • Prefer AddNabsApis / UseNabsApis (or equivalent AddOpenApi + MapOpenApi) so the document matches mapped endpoints.
  • Export with TryExportOpenApiAndExitAsync("--export-openapi") and/or Nabs.Launchpad.Core.Apis.OpenApi.Export for Kiota clients.
  • Treat breaking OpenAPI changes as breaking API changes (CI OpenAPI diff is a follow-up; see Discussion #10).

Errors use Problem Details

  • Ardalis Result failures map to Problem Details with status-code mappings (for example NotFound404, Conflict409).
  • FluentValidation request failures map to HTTP 400 ValidationProblem.
  • Response validation failures map to HTTP 500 Problem Details.
  • Do not return bare error strings for API failures from Nabs endpoint handlers.

Authentication (default AddNabsApis)

  • UseOpenApi and UseJwtBearerAuthentication default to true.
  • Default OpenAPI includes an HTTP Bearer JWT security scheme and document-level security requirement.
  • Configure Authentication:JwtBearer (Issuer, Audience, SigningKey) when JWT is enabled.
  • Opt out explicitly when needed: AddNabsApis(configuration, o => o.UseJwtBearerAuthentication = false).

Gateway vs service

  • Interactive login / OIDC (Entra) belongs at Gateway (Nabs.Launchpad.Core.Gateway).
  • API services validate Bearer JWT (issued or forwarded by the gateway) via AddNabsApis or equivalent shared authentication setup.
  • Observability defaults live in ServiceDefaults and pair with API hosts in Aspire.

Out of scope for this package contract

URI conventions, pagination helpers, and API versioning are separate ideas:

Configuration

No package-specific configuration is required for endpoint mapping.

NabsEndpointOptions supports one or more HttpMethod values and validates them against a supported set: GET, POST, PUT, DELETE, PATCH, QUERY, SELECT, HEAD, OPTIONS, TRACE, and CONNECT. When multiple methods are configured, only GET, QUERY, SELECT, HEAD, and OPTIONS combinations are allowed. Use NabsHttpMethods.Select for the non-standard SELECT method.

If you need to treat validation feedback as non-blocking, set ReturnOkOnInvalidResult = true in NabsEndpointOptions. This causes ParseResult(...) to return 200 OK with a validationErrors payload even when the Ardalis result status is Invalid.

For successful Ardalis results, ParseResult(...) maps the status code based on the configured endpoint HTTP method: POST returns 201 Created, DELETE returns 204 No Content when no payload is returned (otherwise 200 OK), and all other supported methods return 200 OK.

Project Structure

  • NabsGetEndpoint.cs / NabsPostEndpoint.cs (and other verb bases) - preferred convenience bases
  • INabsEndpoint.cs - contract for one endpoint per class/file
  • NabsEndpointBase.cs - declarative base class with override-driven configuration
  • NabsEndpointBaseOfT.cs - typed base for request/response endpoints (use NabsNone for missing request or response payloads)
  • NabsEndpointOptions.cs - route/method + metadata (canonical) and verb factories
  • NabsNone.cs - marker type representing no request or no response payload
  • NabsEndpointRouteBuilderExtensions.cs - endpoint discovery and mapping extensions
  • NabsOpenApiExportExtensions.cs - --export-openapi host self-export
  • NabsApisServiceCollectionExtensions.cs / NabsApisApplicationBuilderExtensions.cs - optional host helpers
  • NabsControllerBase.cs - reusable base class for controller-based APIs

License

Copyright (c) Net Advantage Business Solutions.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Nabs.Launchpad.Core.Apis:

Package Downloads
Nabs.Launchpad.Core.FeatureFlags

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.287 0 9/21/2026
10.0.286 45 9/18/2026
10.0.285 43 9/18/2026
10.0.273 114 9/6/2026
10.0.272 102 9/5/2026
10.0.270 99 9/5/2026
10.0.269 97 9/5/2026
10.0.255 116 7/26/2026
10.0.250 120 6/23/2026
10.0.249 121 6/6/2026
10.0.248 117 6/6/2026
10.0.247 116 6/6/2026
10.0.246 124 6/6/2026
10.0.242 111 6/4/2026
10.0.241 110 6/4/2026
10.0.240 114 6/4/2026
10.0.239 110 6/3/2026
10.0.234 110 5/31/2026
10.0.233 112 5/31/2026
10.0.232 110 5/30/2026
Loading failed