ApiFluentResults.AspNetCore 2.0.1

dotnet add package ApiFluentResults.AspNetCore --version 2.0.1
                    
NuGet\Install-Package ApiFluentResults.AspNetCore -Version 2.0.1
                    
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="ApiFluentResults.AspNetCore" Version="2.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ApiFluentResults.AspNetCore" Version="2.0.1" />
                    
Directory.Packages.props
<PackageReference Include="ApiFluentResults.AspNetCore" />
                    
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 ApiFluentResults.AspNetCore --version 2.0.1
                    
#r "nuget: ApiFluentResults.AspNetCore, 2.0.1"
                    
#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 ApiFluentResults.AspNetCore@2.0.1
                    
#: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=ApiFluentResults.AspNetCore&version=2.0.1
                    
Install as a Cake Addin
#tool nuget:?package=ApiFluentResults.AspNetCore&version=2.0.1
                    
Install as a Cake Tool

ApiFluentResults

A lightweight solution to map FluentResults to HTTP responses in ASP.NET Core using ProblemDetails, keeping controllers clean and aligned with Clean Architecture and the Result Pattern.

The solution is split into two NuGet packages to support modular and layered architectures.


Packages

ApiFluentResults.Domain

Contains standard and base error types that can be used from any layer (Domain / Application) without depending on ASP.NET Core.

This package is intended to be referenced from core layers in Clean Architecture.

Included errors:

  • NotFoundError
  • ConflictError
  • ValidationError
  • UnauthorizedError
  • ForbiddenError
  • DomainError
  • BaseFluentError (base class for all errors)
dotnet add package ApiFluentResults.Domain

ApiFluentResults.AspNetCore

Provides ASP.NET Core integration to:

  • Automatically map FluentResults errors
  • Resolve the correct HTTP status code
  • Return standardized ProblemDetails responses
  • Support custom domain errors without controller boilerplate

This package depends on ApiFluentResults.Domain.

dotnet add package ApiFluentResults.AspNetCore

Getting Started

Base Controller

Inherit from FluentResultController to enable result mapping:

public class FluentResultController : ControllerBase
{
    protected ResultMapper<T> MapResult<T>(Result<T> result) => new(result, this);

    protected ResultMapper<object> MapResult(Result result) =>
        new(result.ToResult<object>(), this);
}

Controller Usage Example

Public class OrdersController : FluentResultController
{
    // ...
    [HttpPost("{id}/pay")]
    public async Task<IActionResult> PayOrder(
        [FromRoute] long id,
        [FromBody] List<PayOrderCommand.PaymentDto> payOrders
    )
    {
        var command = new PayOrderCommand(id, payOrders);
        var result = await Mediator.Send(command);

        return MapResult(result)
            .ConflictFor<OrderAlreadyPaidError>()
            .Ok();
    }
}

No switch statements No if/else chains No HTTP concerns leaking into Application or Domain layers

Supported Success Responses

Ok()
.OkEmpty()
.Created()
.CreatedAtAction()
.NoContent()
.Accepted()
.Status(StatusCode...)

Example:

return MapResult(result)
    .Created();

Default Error Mappings

The following error types are mapped automatically:

Error Type HTTP Status
NotFoundError 404
ConflictError 409
ValidationError 400
UnauthorizedError 401
ForbiddenError 403
DomainError 422

Business Rule Validation

You can return multiple validation errors using DomainError or your custom error:

       public static Result<Order> Create(
                int branchId,
                int orderTypeId,
                string currencyCode,
                string orderNumber,
                CustomerSnapshot customerSnapshot,
                long? customerId,
                decimal? descountAmount = 0,
                long? tableSessionId = null
            )
            {
                if (branchId is 0)
                    return Result.Fail(new DomainError("Branch is required"));

                if (orderTypeId is 0)
                    return Result.Fail(new DomainError("Type order is required"));
                  .....

                return new Order(
                    branchId,
                    orderTypeId,
                    currencyCode,
                    orderNumber,
                    customerSnapshot,
                    customerId,
                    descountAmount,
                    tableSessionId
                );
            }

Custom Errors

You can define your own business errors by inheriting from BaseFluentError, It is not necessary to map the error code, as by default the status code will be 422 (Unprocessable Entity).:

public class OrderAlreadyPaidError : BaseFluentError
{
    public OrderAlreadyPaidError(string orderNumber)
        : base(
            $"Order {orderNumber} has already been paid.",
            "ORDER_ALREADY_PAID"
        )
    {
        Metadata.Add("orderId", orderNumber);
    }
}

If you want a different type of error, assign the error to an HTTP status code in the controller:

return MapResult(result)
    .ConflictFor<OrderAlreadyPaidError>()
    .Ok();

Custom Status Code Mapping

If there is no predefined method for the HTTP status you need, you can use CustomErrorFor:

return MapResult(result)
    .CustomErrorFor<OrderAlreadyPaidError>(418)
    .Ok();

This allows full control over the returned HTTP status code.

ProblemDetails Response Format

All error responses follow the ProblemDetails standard, with additional support for:

  • code (business error code)
  • metadata
  • errors (validation errors)

Example response:

{
  "type": "https://httpstatuses.com/409",
  "title": "Conflict",
  "status": 409,
  "detail": "Order 123 has already been paid.",
  "instance": "/api/orders/123/pay",
  "code": "ORDER_ALREADY_PAID",
  "metadata": {
    "orderId": "123"
  }
}

Benefits

  • Clean and declarative controllers
  • Clear separation between domain logic and HTTP concerns
  • Fully compatible with FluentResults
  • Ideal for Clean, Hexagonal, and Modular Architectures
  • Consistent and standardized HTTP error responses

When to Use

  • ASP.NET Core APIs
  • Applications using the Result Pattern
  • Systems with explicit business rules
  • Teams looking to reduce controller boilerplate
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

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
2.0.1 95 2/4/2026
2.0.0 98 2/3/2026
1.3.2 92 2/3/2026
1.3.1 120 1/25/2026
1.2.1 104 1/25/2026
1.1.0 293 12/16/2025
1.0.1 206 11/25/2025
1.0.0 208 11/24/2025

- update readme