RadEndpoints.Testing 1.0.0-alpha.8

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

// Install RadEndpoints.Testing as a Cake Tool
#tool nuget:?package=RadEndpoints.Testing&version=1.0.0-alpha.8&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

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
1.0.0-alpha.8 120 4/29/2024
1.0.0-alpha.5 54 4/28/2024
1.0.0-alpha.4 81 2/24/2024
1.0.0-alpha.3 59 2/23/2024
1.0.0-alpha.2 63 2/21/2024
1.0.0-alpha.1 60 2/21/2024