ViniBas.ResultPattern
1.0.0
dotnet add package ViniBas.ResultPattern --version 1.0.0
NuGet\Install-Package ViniBas.ResultPattern -Version 1.0.0
<PackageReference Include="ViniBas.ResultPattern" Version="1.0.0" />
<PackageVersion Include="ViniBas.ResultPattern" Version="1.0.0" />
<PackageReference Include="ViniBas.ResultPattern" />
paket add ViniBas.ResultPattern --version 1.0.0
#r "nuget: ViniBas.ResultPattern, 1.0.0"
#:package ViniBas.ResultPattern@1.0.0
#addin nuget:?package=ViniBas.ResultPattern&version=1.0.0
#tool nuget:?package=ViniBas.ResultPattern&version=1.0.0
ViniBas.ResultPattern
Copyright (c) Vinícius Bastos da Silva 2025 Licensed under the GNU Lesser General Public License v3 (LGPL v3). See the LICENSE.txt file for details.
Introduction
This project consists of two .NET libraries, available for use via NuGet, aimed at implementing the Result Pattern in a simple, clean, and effective way.
Usage is free, and the code is open-source under the LGPL v3 license. Check the LICENSE.txt file in the project root for more information.
The two libraries that make up this project are: ResultPattern, which is the core of the project, and ResultPattern.AspNet, which contains resources for use in ASP.NET projects. Below are instructions for each.
ViniBas.ResultPattern
The ResultPattern library is the main library of the project. It contains the Result and ResultResponse objects and is independent of the project type: ASP.NET, Console, Class Library, etc. Since it has no external dependencies, it can even be used in business logic layers without contaminating your domain with infrastructure details.
The ResultPattern package contains two main object types: Result and ResultResponse. Let's discuss the importance of each:
Result
The Result class is the most important class in the entire project. This is the class we actually use as the return type in our service methods, indicating success or failure. The Result class may or may not have an associated object. In this case, we use Result<T>, where T is the type of the return object, which will be available in the Data property in case of success.
Some implementations of the Result Pattern force verbose and hard-to-read returns, requiring object construction and redundant type declarations. In this library, you have more flexibility, allowing you to return either an Error object (or a collection of them) or the expected value in case of success, as in the following example:
public Result<string> Get()
{
if (somethingWrong)
return Error.Failure("ErrorCode", "Error message!");
if (severalThingsWrong)
return new List<Error>()
{
Error.Validation("Error1", "Some validation 1"),
Error.Validation("Error2", "Some validation 2"),
Error.Validation("Error3", "Some validation 3"),
};
return "Return value on success.";
}
In the example above, we have a situation where we return a list with multiple errors. All of them will be combined into one; the only condition is that they must all have the same type, in this case, Validation.
There are four predefined error types, which can be created using static constructors: Failure, Validation, NotFound, and Conflict. You can create your own custom types by registering them once using Error.ErrorTypes.AddTypes("MyNewErrorType");, and then creating the error using the default constructor: new Error("code", "message", "MyNewErrorType");.
A method calling the example above could validate the result as follows:
var result = Get();
if (result.IsSuccess)
Console.WriteLine(result.Data);
if (result.IsFailure)
foreach (var description in result.Error.ListDescriptions())
Console.WriteLine(description);
If your method does not need to return any value besides the Result itself, you can use Result without T. In this case, since there is no value to return, you can simply return Result.Success();, which would also work with T: return Result.Success("Return value on success.");. Note that Result and Result<T> are different types, so you must return the type declared in your method signature.
ResultResponse
The ResultResponse classes exist to make responses cleaner and more explicit, particularly in cases of JSON serialization. While the Result class is more complete for internal handling, ResultResponse classes represent the final result that can be returned to the user without implementation details. They consist of three classes: ResultResponseError, ResultResponseSuccess, and ResultResponseSuccess<T>, and can be automatically generated from Result.ToResponse().
The structure of the ResultResponse classes always includes an IsSuccess property. In case of an error, there is a list of Errors (strings) and a Type (string) indicating the error type. In case of success, there may be a Data property containing the return value.
ViniBas.ResultPattern.AspNet
The ResultPattern.AspNet library provides additional features for both ASP.NET Web API and Minimal API. The main feature is the Match method, which allows mapping API return functions for success or failure cases. It is even possible to omit the failure method, which results in a ProblemDetails response with the appropriate status code for the error type in Result. This way, the developer does not need to manually map the status code for each error type in Result. For example, if Result contains NotFound errors, the returned status code will be 404. For Failure, it will be 500.
For custom error types, just as we can create new error types with Error.ErrorTypes.AddTypes("MyNewErrorType");, we can also create new mappings by modifying the Maps dictionary, for example:
ErrorTypeMaps.Maps.Add("MyNewErrorType", (StatusCodes.Status406NotAcceptable, "My New Error Type"));.
This way, the new type will always return the mapped status code, and the corresponding title will be used. It is also possible to modify existing mappings. If an error type is not pre-mapped, the default status code returned is 500.
See an example of usage in an MVC action:
[HttpGet("{value}")]
public IActionResult Get()
=> _myService.GetResult().Match(Ok);
In the example below, using Minimal API, we can return an IResult or Results<> for typed responses:
app.MapGet("IResult", ()
=> myService.Get().Match(Results.Ok));
app.MapGet("Results<>", ()
=> myService.Get().Match<Results<Ok, ProblemHttpResult>, Ok>(TypedResults.Ok));
Again, the second parameter is optional, so it is omitted in the examples, returning a ProblemDetails object by default.
The Problem Details standard is based on RFC 7807, and the returned object is native to ASP.NET, as described in the official documentation.
The returned ProblemDetails object includes the following additional properties:
isSuccess: a fixed boolean with the valuefalse;errors: the list of error descriptions.
Two filters are also included: ActionResultFilter for ASP.NET MVC and ResultsResultFilter for Minimal API. These filters ensure that if objects such as Result, Error, or ResultResponse are returned directly, they are properly converted into a ResultResponseSuccess or a ProblemDetails.
To facilitate validation in MVC applications, it is also possible to easily convert a ModelState into an Error object or an IActionResult with a ProblemDetails using the extension methods ModelStateToError and ToProblemDetailsActionResult.
Demo
We have a demonstration ASP.NET project with some simple examples, which can be found in the samples folder of the repository at https://github.com/vinibas/ResultPattern/.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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. |
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ViniBas.ResultPattern:
| Package | Downloads |
|---|---|
|
ViniBas.ResultPattern.AspNet
Library that implements the Result Pattern in Asp.net in a clean and flexible way. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 284 | 3/10/2025 |