RadEndpoints 1.0.0-alpha.6

This is a prerelease version of RadEndpoints.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package RadEndpoints --version 1.0.0-alpha.6                
NuGet\Install-Package RadEndpoints -Version 1.0.0-alpha.6                
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="RadEndpoints" Version="1.0.0-alpha.6" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add RadEndpoints --version 1.0.0-alpha.6                
#r "nuget: RadEndpoints, 1.0.0-alpha.6"                
#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 RadEndpoints as a Cake Addin
#addin nuget:?package=RadEndpoints&version=1.0.0-alpha.6&prerelease

// Install RadEndpoints as a Cake Tool
#tool nuget:?package=RadEndpoints&version=1.0.0-alpha.6&prerelease                

RadEndpoints

An API library bringing REPR-style endpoint classes to .NET Minimal API.

Library Goals

Should be:

  • Lightweight -- and easy to work with or without.
  • Junior Developer Friendly -- without impeding more experienced engineers.
  • Backward Compatible -- with Minimal API configuration and features.
  • Configurable -- using MinimalApi RouteHandlerBuilder.
  • Well Structured -- for common tasks such as validation, mapping and error handling.
  • Extensible -- to allow for custom alternate endpoint implmentations.
  • Fast and Easy -- to rapidly scaffold projects, endpoints and tests.
  • Low Maintenance -- for testing.

Features:

REPR Endpoint Classes
  • Reduced configuration noise over minimal api endpoints
  • Constructor dependency injection
  • Scoped lifetime
  • Assembly scanned and configured request validator and model mapper
  • Built-in Endpoint Class Conveniences
    • HttpContext
    • Logger
    • Environment Info
    • Response Object
    • Model Mapper
    • TypedResult Shortcuts
public class GetSampleEndpoint(ISampleService sampleService) : RadEndpoint<GetSampleRequest, GetSampleResponse, GetSampleMapper>
{
    public override void Configure()
    {
        Get("/samples/{id}")
            .Produces<GetSampleResponse>(StatusCodes.Status200OK)            
            .ProducesProblem(StatusCodes.Status404NotFound)
            .ProducesValidationProblem()
            .WithDocument(tag: "Sample", desc: "Get Sample by ID");

            //Any NET minimal api (RouteHandlerBuilder) configuration works here.
    }

    public override async Task Handle(GetSampleRequest r, CancellationToken ct)
    {
        var sample = await sampleService.GetSampleById(r.Id, ct);

        if(sample is null)
        {
            SendNotFound("Sample not found.");
            return;
        }
        Response = Map.FromEntity(sample);
        Send();
    }
}
Request Model Binding and Validation
  • Automatic request model binding from route, query, header, and body using [AsParameters].
  • Automatic request model validation execution using FluentValidation
public class GetSampleRequest
{
    [FromRoute]
    public int Id { get; set; }
}

public class GetSampleRequestValidator : AbstractValidator<GetSampleRequest>
{
    public GetSampleRequestValidator()
    {
        RuleFor(e => e.Id).GreaterThan(0);
    }
}

public class GetSampleResponse
{
    public SampleDto Data { get; set; } = null!;
    public string Message { get; set; } = "Sample retrieved successfully";
}
Endpoint Model Mapper
  • Assign mappers for conventient access from endpoint
  • Makes mapping a first class citizen with the endpoint configuration
  • Map manually or with a mapping tool like AutoMapper or Mapster
public class GetExampleMapper : IRadMapper<GetExampleRequest, GetExampleResponse, Example>
{
    public GetExampleResponse FromEntity(Example e) => new()
    {
        Data = new()
        {
            Id = e.Id,
            FirstName = e.FirstName,
            LastName = e.LastName
        }
    };
    public Example ToEntity(GetExampleRequest r) => throw new NotImplementedException();
}
Flexibility and Alternate Base Endpoint Class
  • Don't like the endpoint base classes? Make your own using the included abstractions.
  • Want to use a bare minimum REPR endpoint with Open Union Types? Go for it.
  • Need to create a super specialized edge case endpoint with pure minimal api endpoint? No problem.
  //Code samples coming soon
Integration Testing
  • Strongly typed "Routeless" HttpClient extensions
  • Reduced maintenance with automatic endpoint route discovery and request model binding
  • Easy to navigate to endpoint code from test
  • Consistent and convenient response assertions for HttpResponse and ProblemDetails using FluentAssertions
  • Detailed exception messages so you dig less to find test issues.
[Fact]
public async void When_RequestValid_ReturnsSuccess()
{
    //Arrange
    var request = new GetSampleRequest { Id = 1 };

    //Act       
    var r = await f.Client.GetAsync<GetSampleEndpoint, GetSampleRequest, GetSampleResponse>(request);

    //Assert
    r.Should()
        .BeSuccessful<GetSampleResponse>()
        .WithStatusCode(HttpStatusCode.OK);
}

CLI For Scaffolding

  • Scaffold multiple new endpoints very quickly.
  • Import a set of endoints using a JSON definition.
  • Full parameter support for 1 line endpoint creation.
Endpoint Wizard

<img src="https://github.com/MetalHexx/RadEndpoints/assets/9291740/8782c1e9-ef40-4c0b-9b1c-dc9f96ae3826" width="60%" height="60%" alt="Description of Image"/>

JSON definition
[
  {
    "BaseNamepace": "Demo.Api.Endpoints",
    "ResourceName": "User",
    "Verb": "Get",
    "EndpointName": "GetUser",
    "Path": "/users/{id}",
    "Entity": "User",
    "Tag": "User",
    "Description": "Get User by ID",
    "WithMapper": true
  },
  {
    "BaseNamepace": "Demo.Api.Endpoints",
    "ResourceName": "User",
    "Verb": "Post",
    "EndpointName": "CreateUser",
    "Path": "/users",
    "Entity": "User",
    "Tag": "User",
    "Description": "Create a new User",
    "WithMapper": true
  }
  ...other endpoints.
]
Bulk JSON Import

<img src="https://github.com/MetalHexx/RadEndpoints/assets/9291740/eafc6050-9afd-4c4b-a844-a6b1033b9f98" width="60%" height="60%" alt="Description of Image"/>

Coming Soon:

  • Project templates
  • Observability Tooling
  • Additional code coverage
  • Documentation / How Tos

Credits

  • FastEndpoints -- as many of the ideas from that project inspired this one.
Product Compatible and additional computed target framework versions.
.NET 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 (1)

Showing the top 1 NuGet packages that depend on RadEndpoints:

Package Downloads
RadEndpoints.Testing

Make testing easier with RadEndpoints

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0-alpha.9 39 11/15/2024
1.0.0-alpha.8 465 4/29/2024
1.0.0-alpha.7 53 4/29/2024
1.0.0-alpha.6 53 4/29/2024
1.0.0-alpha.5 55 4/28/2024
1.0.0-alpha.4 73 2/24/2024
1.0.0-alpha.3 59 2/23/2024
1.0.0-alpha.2 73 2/21/2024
1.0.0-alpha.1 67 2/21/2024