BonyadCode.Resulter.AspNetCore 1.0.9

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

BonyadCode.Resulter.AspNetCore

A robust utility library to standardize API responses in ASP.NET Core. Supports both Controllers and Minimal APIs with unified handling of success, failure, validation errors, and exceptions โ€” using rich ProblemDetails in accordance with RFC7807 and RFC9457 standards.


โœจ 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.

๐Ÿ“ฆ 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)

[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
}

โœ… 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()
        .AddErrorsFromKeyValuePairs("Email", "Email is required.")
        .AddErrorsFromKeyValuePairs("Password", new List<string> { "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.",
    "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();
});

Response JSON:

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

โŒ FluentValidation Errors

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

    if(!validationResult.Succeeded)
    {
        var result = ResultBuilder<string>.Failure()
            .AddErrorsFromFluentValidationResult(validationResult);
    }
    
    return result.ToHttpResultMinimal();
});

โš™๏ธ Custom ProblemDetails Examples

๐Ÿ› ๏ธ Attach Custom Metadata

var result = ResultBuilder<string>.Failure()
    .WithCustomProblemDetails(
        type: "https://example.com/problems/validation",
        title: "Validation Error",
        details: "One or more validation failures occured.",
        statusCode: HttpStatusCode.Conflict,
        instance: "/api/register",
        errors: new Dictionary<string, object?>
        {
            { "Username", new[] { "Username already exists." } }
        });

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

Response JSON:

{
  "succeeded": false,
  "statusCode": 400,
  "data": null,
  "problemDetails": {
    "type": "https://example.com/problems/validation",
    "title": "Validation Error",
    "detail": "One or more validation 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()
    .AddErrorsFromValidationResult(validationResult);

๐Ÿงช FluentValidation

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

๐Ÿ” IdentityResult

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

๐Ÿ”ฅ Exception Handling

try
{
    throw new InvalidOperationException("Something broke.");
}
catch (Exception ex)
{
    var result = ResultBuilder.Failure()
        .WithExceptionProblemDetails(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": "An exception was thrown.",
    "detail": "Something broke.",
    "status": 500,
    "instance": "/api/failing-endpoint",
    "extensions": {
      "Message": ["Something broke."],
      "Source": ["MyApp"]
    }
  }
}

๐Ÿ“š Extension Reference

Method Description
WithSimpleProblemDetails() Attaches default problem info
WithCustomProblemDetails(...) Fully customized metadata
WithExceptionProblemDetails(...) Wraps exception details
AddErrorsFromKeyValuePairs(...) Adds custom errors by key/value(s)
AddErrorsFromFluentValidationResult(...) Maps FluentValidation errors
AddErrorsFromValidationResult(...) Maps DataAnnotation errors
AddErrorsFromIdentityError(...) Maps IdentityResult errors
AddProblemDetailsErrorExtensionsFromException(...) Adds public exception properties

๐Ÿงช API Behavior Matrix

Scenario Method Status Code Description
Success ResultBuilder.Success() 200 OK Standard success with optional data
Failure ResultBuilder.Failure() 400 Bad Request Generic or validation failure
Exception .WithExceptionProblemDetails() 500 Internal Server Error Captures exception stack trace
Custom Error .WithCustomProblemDetails(...) 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.1 5 6/5/2025
1.1.0 14 6/4/2025
1.0.9 35 6/3/2025
1.0.8 56 6/2/2025
1.0.7 68 5/24/2025