BonyadCode.Resulter.AspNetCore 1.1.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package BonyadCode.Resulter.AspNetCore --version 1.1.1
                    
NuGet\Install-Package BonyadCode.Resulter.AspNetCore -Version 1.1.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="BonyadCode.Resulter.AspNetCore" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BonyadCode.Resulter.AspNetCore" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="BonyadCode.Resulter.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 BonyadCode.Resulter.AspNetCore --version 1.1.1
                    
#r "nuget: BonyadCode.Resulter.AspNetCore, 1.1.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.
#addin nuget:?package=BonyadCode.Resulter.AspNetCore&version=1.1.1
                    
Install BonyadCode.Resulter.AspNetCore as a Cake Addin
#tool nuget:?package=BonyadCode.Resulter.AspNetCore&version=1.1.1
                    
Install BonyadCode.Resulter.AspNetCore as a Cake Tool

In the name of God

BonyadCode.Resulter.AspNetCore

A utility library to standardize API responses in ASP.NET Core. It supports both Controllers and Minimal APIs with consistent handling of success, failure, validation errors, and exceptions, using rich ProblemDetails following RFC7807.

โœจ Features

  • Unified Result Model: Consistent ResultBuilder<T> and ResultBuilder for all HTTP outcomes.
  • Support for Minimal APIs & Controllers: Seamlessly convert to IActionResult or IResult.
  • ProblemDetails Integration: Built-in helpers to enrich error responses with metadata.
  • Zero Boilerplate: Clean, expressive syntax that reduces repetitive response code.
  • Validation: and Error Support: Maps errors from FluentValidation, DataAnnotations, and IdentityResult into structured responses.

๐Ÿ“ฆ Installation

dotnet add package BonyadCode.Resulter.AspNetCore

๐Ÿš€ Quick Examples

โœ… Success (Controller)

[HttpGet("hello")]
public IActionResult GetHello()
{
    var result = ResultBuilder<string>.Success("Hello, world!");
    return result.ToHttpResultController();
}

Response JSON:

{
  "succeeded": true,
  "statusCode": 200,
  "data": "Hello, world!",
  "problemDetails": null
}

โœ… Success (Minimal Api)

app.MapGet("/hello", () =>
{
    var result = ResultBuilder<string>.Success("Hello, world!");
    return result.ToHttpResultMinimal();
});

Response JSON:

{
  "succeeded": true,
  "statusCode": 200,
  "data": "Hello, world!",
  "problemDetails": null
}

โœ… Custom Success (Controller)

[HttpGet("hello")]
public IActionResult GetHello()
{
    var result = ResultBuilder.Success("User was Created", HttpStatusCode.Created);
    return result.ToHttpResultController();
}

Response JSON:

{
  "succeeded": true,
  "statusCode": 201,
  "data": "User was Created",
  "problemDetails": null
}

โœ… Custom Success (Minimal Api)

app.MapGet("/hello", () =>
{
    var result = ResultBuilder.Success("User was Created", HttpStatusCode.Created);
    return result.ToHttpResultMinimal();
});

Response JSON:

{
  "succeeded": true,
  "statusCode": 201,
  "data": "User was Created",
  "problemDetails": null
}

โŒ Validation Failure (Controller)

[HttpPost("register")]
public IActionResult RegisterUser(UserDto dto)
{
    var result = ResultBuilder<string>.Failure()
        .AddProblemDetailsFromKeyValuePairs("Email", "Email is required.")
        .AddProblemDetailsFromKeyValuePairs("Password", "Password must be at least 8 characters." );

    return result.ToHttpResultController();
}

or

[HttpPost("register")]
public IActionResult RegisterUser(UserDto dto)
{
    var result = ResultBuilder<string>.Failure()
        .AddProblemDetailsFromKeyValuePairs(["Email","Password"], ["Email is required.","Password must be at least 8 characters." ]);

    return result.ToHttpResultController();
}

Response JSON:

{
  "succeeded": false,
  "statusCode": 400,
  "data": null,
  "problemDetails": {
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "A problem occurred.",
    "detail": "A problem occurred (400 BadRequest).",
    "status": 400,
    "extensions": {
      "Email": [
        "Email is required."
      ],
      "Password": [
        "Password must be at least 8 characters."
      ]
    }
  }
}

๐ŸŒ Minimal API Usage

โœ… Success

app.MapGet("/status", () =>
{
    var result = ResultBuilder<string>.Success("All systems operational.", HttpStatusCode.NoContent);
    return result.ToHttpResultMinimal();
});

or

app.MapGet("/status", () =>
{
    var result = ResultBuilder<string>.Success("All systems operational.");
    return result.ToHttpResultMinimal(HttpStatusCode.NoContent);
});

Response JSON:

{
  "succeeded": true,
  "statusCode": 204,
  "data": "All systems operational.",
  "problemDetails": null
}

โŒ FluentValidation Errors

app.MapPost("/login", (LoginRequest request, HttpContext? httpContext, IValidator<LoginRequest> validator) =>
{
    var validationResult = validator.Validate(request);

    if(!validationResult.Succeeded)
    {
        var result = ResultBuilder<string>.Failure()
            .AddProblemDetailsFromFluentValidationResult(validationResult);

        return result.ToHttpResultMinimal(HttpStatusCode.Conflict, httpContext);
    }

    return ResultBuilder<string>.Success("Logged in").ToHttpResultMinimal();
});

Response JSON:

{
  "succeeded": false,
  "statusCode": 409,
  "data": null,
  "problemDetails": {
    "type": "https://example.com/problems/validation",
    "title": "A validation problem occurred.",
    "detail": "One or more validation failures occured.",
    "status": 409,
    "instance": "/api/register",
    "extensions": {
      "Username": [
        "Username already exists."
      ]
    }
  }
}

โš™๏ธ Custom ProblemDetails Examples

๐Ÿ› ๏ธ Attach Custom Metadata

var result = ResultBuilder<string>.Failure()
    .AddCustomProblemDetails(
        type: "https://example.com/problems/validation",
        title: "A custom problem occurred.",
        details: "One or more custom failures occured.",
        statusCode: HttpStatusCode.Conflict,
        instance: "/api/register",
        extensions: new Dictionary<string, object?>
        {
            { "Username", new[] { "Username already exists." } }
        }).ToHttpResultMinimal(HttpStatusCode.Conflict, httpContext);

Note: You can pass the httpContext to the above method so that "instance" is extracted automatically from it.

Response JSON:

{
  "succeeded": false,
  "statusCode": 409,
  "data": null,
  "problemDetails": {
    "type": "https://example.com/problems/validation",
    "title": "A custom problem occurred.",
    "detail": "One or more custom failures occured.",
    "status": 409,
    "instance": "/api/register",
    "extensions": {
      "Username": [
        "Username already exists."
      ]
    }
  }
}

๐Ÿง Validation Sources

๐Ÿ”ง DataAnnotations

var validationResult = new ValidationResult("Email", new[] { "Invalid email" });
var result = ResultBuilder.Failure()
    .AddProblemDetailsFromValidationResult(validationResult);

๐Ÿงช FluentValidation

var result = ResultBuilder.Failure()
    .AddProblemDetailsFromFluentValidationResult(validationResult);

๐Ÿ” IdentityResult

var result = ResultBuilder.Failure()
    .AddProblemDetailsFromIdentityError(identityResult);

๐Ÿ”ฅ Exception Handling

try
{
    throw new InvalidOperationException("Something broke.");
}
catch (Exception ex)
{
    var result = ResultBuilder.Failure()
        .AddProblemDetailsFromException(ex, httpContext);

    return result.ToHttpResultController();
}

Response JSON (truncated):

{
  "succeeded": false,
  "statusCode": 500,
  "data": null,
  "problemDetails": {
    "type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
    "title": "A Server problem occurred.",
    "detail": {
      "message": "Something broke."
    },
    "status": 500,
    "instance": "/api/failing-endpoint",
    "extensions": {
      "Message": [
        "Something broke."
      ],
      "Source": [
        "MyApp"
      ]
    }
  }
}

๐Ÿ“š Extension Reference

Endpoint Result Methods:

Method Description
ToHttpResultController() returns an IActionResult result for use in Controllers
ToHttpResultController(...) returns an IActionResult result for use in Controllers (accepting parameters)
ToHttpResultMinimal() returns an IResult result for use in Minimal
ToHttpResultMinimal(...) returns an IResult result for use in Minimal APIs (accepting parameters)

ProblemDetails Helper Methods:

Method Description
AddSimpleProblemDetails() Attaches default problem info
AddCustomProblemDetails(...) Fully customized metadata
AddProblemDetailsFromException(...) Adds public exception properties
AddProblemDetailsFromIdentityError(...) Maps IdentityResult errors
AddProblemDetailsFromFluentValidationResult(...) Maps FluentValidation errors
AddProblemDetailsFromValidationResult(...) Maps DataAnnotation errors
AddProblemDetailsFromKeyValuePairs(...) Adds custom errors by key/value(s)

๐Ÿงช API Behavior Matrix

Scenario Method Status Code Description
Success ResultBuilder.Success() Any (Default: 200 OK) Standard success with optional data
Failure ResultBuilder.Failure() Any (Default: 400 Bad Request) Standard failure with optional data (exception, validation, etc.)
Create ResultBuilder.Create() Any User-defined structured error response

๐Ÿค Contributing

PRs and feedback welcome! GitHub โ†’

๐Ÿ“„ License

Apache 2.0 โ€” see the LICENSE file.

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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
1.1.2 101 6/8/2025
1.1.1 131 6/5/2025
1.1.0 130 6/4/2025
1.0.9 134 6/3/2025
1.0.8 132 6/2/2025
1.0.7 70 5/24/2025