BonyadCode.Resulter.AspNetCore
1.0.9
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
<PackageReference Include="BonyadCode.Resulter.AspNetCore" Version="1.0.9" />
<PackageVersion Include="BonyadCode.Resulter.AspNetCore" Version="1.0.9" />
<PackageReference Include="BonyadCode.Resulter.AspNetCore" />
paket add BonyadCode.Resulter.AspNetCore --version 1.0.9
#r "nuget: BonyadCode.Resulter.AspNetCore, 1.0.9"
#addin nuget:?package=BonyadCode.Resulter.AspNetCore&version=1.0.9
#tool nuget:?package=BonyadCode.Resulter.AspNetCore&version=1.0.9
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>
andResultBuilder
for all HTTP outcomes. - Support for Minimal APIs & Controllers: Seamlessly convert to
IActionResult
orIResult
. - 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.
๐ฆ Links
Product | Versions 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. |
-
net8.0
- FluentValidation (>= 12.0.0)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.