Wrapper to transfer results or errors between layers or resources
- Support to
- How to use
- Contribution
- .NET 8.0
- .NET 7.0
- .NET 6.0
- .NET 5.0
This package is available through Nuget Packages: https://www.nuget.org/packages/PowerUtils.Results
Nuget
Install-Package PowerUtils.Results
.NET CLI
dotnet add package PowerUtils.Results
// Void result
var result = Result.Ok();
var result = Result.Success();
// Result with typed value
var model = new Model();
var result = Result<Model>.Ok(model);
var result = Result.Ok<Model>(model);
var result = Result.Ok(model);
var result = Result.Success(model);
// Implicit assignment
Result<Model> result = model;
Result result = new Success();
Result result = Error.Failure("property", "code", "description");
Result result = Error.Unauthorized("property", "code", "description");
Result result = Error.Forbidden("property", "code", "description");
Result result = Error.NotFound("property", "code", "description");
Result result = Error.Conflict("property", "code", "description");
Result result = Error.Validation("property", "code", "description");
Result result = Error.Unexpected("property", "code", "description");
// Implicit assignment
Result result = new Error("property", "code", "description");
Result result = new UnauthorizedError("property", "code", "description");
Result result = new ForbiddenError("property", "code", "description");
Result result = new NotFoundError("property", "code", "description");
Result result = new ConflictError("property", "code", "description");
Result result = new ValidationError("property", "code", "description");
Result result = new UnexpectedError("property", "code", "description");
// Error list
var errors = new List<Error>
{
new Error("property", "code", "description2"),
new Error("property", "code", "description2")
};
Result result = errors;
Result result = new Error("property", "code", "description");
result.AddError(new Error("property", "code", "description"));
result.AddError("property", "code", "description");
result.AddErrors(new List<Error>
{
new Error("property", "code", "description2"),
new Error("property", "code", "description2")
});
Error.Error()
;Error.Unauthorized()
Error.Forbidden()
Error.NotFound()
Error.Conflict()
Error.Validation()
Error.Unexpected()
public class CustomError : IError
{
public string Property { get; init; }
public string Code { get; init; }
public string Description { get; init; }
public CustomError(string property, string code, string description)
{
Property = property;
Code = code;
Description = description;
}
}
var error = new CustomError(property, code, description);
var result = Result.From(error);
var result = Result<FakeModel>.From(error);
var result = Result.From<FakeModel>(error);
Creates a Result<TValue>
when the error list is null or empty otherwise creates a result with a list of errors.
Delegate is used to instantiate the value only when there are no errors
// Returns `Result` with value
var result = Result.Create(
Array.Empty<Error>(),
() => new Model());
// Returns `Result` with errors
var result = Result.Create(
new List<Error> { Error.Failure("property", "code", "description") },
() => new Model());
Result result = new Error[]
{
new("Property", "Code", "Description"),
new("Property", "Code", "Description")
};
IError error = result.FirstError();
IError error = result.FirstOrDefaultError();
IError error = result.FirstOrDefaultError(Func<IError, bool> predicate);
IError error = result.LastError();
IError error = result.LastOrDefaultError();
IError error = result.LastOrDefaultError(Func<IError, bool> predicate);
IError error = result.SingleError();
IError error = result.SingleOrDefaultError();
IError error = result.SingleOrDefaultError(Func<IError, bool> predicate);
bool IResult.ContainsError();
bool IResult.ContainsError(Func<IError, bool> predicate);
Result result = Error.Conflict("property", "code", "description");
var type = result.OfTypeFirstError(); // Conflict
Result result = Result.Ok();
var type = result.GetType(); // Success
Result result = Error.Unauthorized("property", "code", "description");
var type = result.GetType(); // UnauthorizedError
Result<Model> result = Error.Forbidden("property", "code", "description");
var type = result.GetType(); // ForbiddenError
var model = new Model();
Result<Model> result = model;
var type = result.GetType(); // Model
bool IResult.IsSuccess();
bool IResult.IsSuccess(Func<TValue, bool> predicate);
result.Switch(
value => onSuccess(value),
errors => onErrors(errors));
// Only return the value or first erro
result.SwitchFirst(
value => onSuccess(value),
error => onError(error));
await result.SwitchAsync(
value => onSuccess(value),
errors => onErrors(errors));
// Only return the value or first erro
await result.SwitchFirstAsync(
value => onSuccess(value),
error => onError(error));
TOutput response = result.Match<TValue, TOutput>(
value => onSuccess(value),
errors => onErrors(errors));
// Only return the value or first erro
TOutput response = result.MatchFirst<TValue, TOutput>(
value => onSuccess(value),
error => onError(error));
Task<TOutput> response = result.MatchAsync<TValue, TOutput>(
value => onSuccess(value),
errors => onErrors(errors));
// Only return the value or first erro
Task<TOutput> response = result.MatchFirstAsync<TValue, TOutput>(
value => onSuccess(value),
error => onError(error));
var errorList = result.Errors.AsList();
Result result = new IError[]
{
Error.Conflict("FakeProperty", "FakeCode", "FakeDescription"),
Error.Conflict("FakeProperty", "FakeCode", "FakeDescription")};
// Only returns one error
var errors = result.DistinctErrors();
var (property, code, description) = Error.Unauthorized("property", "code", "description");
Result<Model> result = new Model { Id = id, Name = name };
// Deconstruct -> value is not null and errors is empty
(var value, var errors) = result;
Result<Model> result = new Model { Id = id, Name = name };
Model model = result;
// Result with errors
Result result = Error.Conflict("property", "code", "description");
List<IError> errors = result;
Valid example
Result<Model> result = new Model { Id = id, Name = name };
// result = implicit conversion "true"
if(result)
{
// Do something
}
// Equivalent to
if(result.IsError == false)
{
// Do something
}
if(result.IsSuccess(out var value, out var errors))
{
// Do something
}
if(result.IsError(out var value, out var errors))
{
// Do something
}
Invalid example
Result result = Error.Conflict("property", "code", "description");
// result = implicit conversion "false"
if(result)
{
// Do something
}
// Equivalent to
if(result.IsError == true)
{
// Do something
}
Serialization Result
success example
var result = Result.Success();
var json = JsonSerializer.Serialize(result);
/*
json = {
"IsSuccess": true
}
*/
var result = Result.Success(45);
var json = JsonSerializer.Serialize(result);
/*
json = {
"IsSuccess": true,
"Value": 45
}
*/
Serialization Result
errors example
Result result = Error.NotFound("client", "NOT_FOUND", "Client not found");
Result<int> result = Error.NotFound("client", "NOT_FOUND", "Client not found");
var json = JsonSerializer.Serialize(result);
/*
json = {
"IsSuccess": false,
"Errors": [
{
"_type": "PowerUtils.Results.NotFoundError",
"Property": "client",
"Code": "NOT_FOUND",
"Description":"Client not found"
}
]
}
*/
Deserialization Result
success example
var json = """
"IsSuccess": true
""";
var result = JsonSerializer.Deserialize<Result>(json);
var json = """
"IsSuccess": true,
"Value": 541.7
""";
var result = JsonSerializer.Deserialize<Result<double>>(json);
Deserialization Result
errors example
var json = """
"IsSuccess": false,
"Errors": [
{
"_type": "PowerUtils.Results.NotFoundError",
"Property": "client",
"Code": "NOT_FOUND",
"Description":"Client not found"
}
]
""";
var result = JsonSerializer.Deserialize<Result>(json);
var result = JsonSerializer.Deserialize<Result<Client>>(json);
Serialization example
var error = Error.NotFound("client", "NOT_FOUND", "Client not found");
var json = JsonSerializer.Serialize(error);
/*
json = {
"_type": "PowerUtils.Results.NotFoundError",
"Property": "client",
"Code": "NOT_FOUND",
"Description": "Client not found"
}
*/
Deserialization example
var json = """
{
"_type": "PowerUtils.Results.NotFoundError",
"Property": "client",
"Code": "NOT_FOUND",
"Description": "Client not found"
}
""";
var error = JsonSerializer.Deserialize<NotFoundError>(json);
For .NET 6.0 or greater, you can use the IError
interface as the type to be deserialized.
To versions .NET 5.0 or lower, the deserialization using interface is not supported by System.Text.Json
. You will get an exception System.NotSupportedException
.
var error = JsonSerializer.Deserialize<IError>(json);
Custom error Serialization/Deserialization example
[JsonConverter(typeof(ErrorJsonConverter<CustomError>))]
public class CustomError : IError { }
If you have any questions, comments, or suggestions, please open an issue or create a pull request