https://github.com/technobre/powerutils.results
Wrapper to transfer results or errors between layers or resources
https://github.com/technobre/powerutils.results
aspnetcore csharp dotnet dto result
Last synced: about 1 year ago
JSON representation
Wrapper to transfer results or errors between layers or resources
- Host: GitHub
- URL: https://github.com/technobre/powerutils.results
- Owner: TechNobre
- License: mit
- Created: 2022-09-04T07:56:50.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-05-22T18:23:47.000Z (about 2 years ago)
- Last Synced: 2024-05-22T19:39:51.516Z (about 2 years ago)
- Topics: aspnetcore, csharp, dotnet, dto, result
- Language: C#
- Homepage:
- Size: 1.98 MB
- Stars: 3
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
Awesome Lists containing this project
README
# PowerUtils.Results

***Wrapper to transfer results or errors between layers or resources***

[](https://dashboard.stryker-mutator.io/reports/github.com/TechNobre/PowerUtils.Results/main)
[](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)
[](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)
[](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)
[](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)
[](https://www.nuget.org/packages/PowerUtils.Results)
[](https://www.nuget.org/packages/PowerUtils.Results)
[](https://github.com/TechNobre/PowerUtils.Results/blob/main/LICENSE)
- [Support to](#support-to)
- [How to use](#how-to-use)
- [Install NuGet package](#install-nuget-package)
- [Creating a Result](#creating-a-result)
- [Success](#success)
- [Errors](#errors)
- [Add more errors](#add-more-errors)
- [Built-in error types](#built-in-error-types)
- [Custom error](#custom-error)
- [Result factory](#result-factory)
- [Extensions](#extensions)
- [Handling errors](#handling-errors)
- [OfTypeFirstError](#oftypefirsterror)
- [Handling success](#handling-success)
- [Switch](#switch)
- [Match](#match)
- [Conversions](#conversions)
- [DistinctErrors](#distincterrors)
- [Deconstruct operators](#deconstruct-operators)
- [Implicit conversion](#implicit-conversion)
- [Check validity](#check-validity)
- [Serialization/Deserialization](#serializationdeserialization)
- [Results](#results)
- [Errors](#errors-1)
- [Contribution](#contribution)
## Support to
- .NET 9.0
- .NET 8.0
- .NET 7.0
- .NET 6.0
- .NET 5.0
## How to use
### Install NuGet package
This package is available through Nuget Packages: https://www.nuget.org/packages/PowerUtils.Results
**Nuget**
```bash
Install-Package PowerUtils.Results
```
**.NET CLI**
```
dotnet add package PowerUtils.Results
```
### Creating a Result
#### Success
```csharp
// Void result
var result = Result.Ok();
var result = Result.Success();
// Result with typed value
var model = new Model();
var result = Result.Ok(model);
var result = Result.Ok(model);
var result = Result.Ok(model);
var result = Result.Success(model);
// Implicit assignment
Result result = model;
Result result = new Success();
```
#### Errors
```csharp
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
{
new Error("property", "code", "description2"),
new Error("property", "code", "description2")
};
Result result = errors;
```
##### Add more errors
```csharp
Result result = new Error("property", "code", "description");
result.AddError(new Error("property", "code", "description"));
result.AddError("property", "code", "description");
result.AddErrors(new List
{
new Error("property", "code", "description2"),
new Error("property", "code", "description2")
});
```
##### Built-in error types
- `Error.Error()`;
- `Error.Unauthorized()`
- `Error.Forbidden()`
- `Error.NotFound()`
- `Error.Conflict()`
- `Error.Validation()`
- `Error.Unexpected()`
##### Custom error
```csharp
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.From(error);
var result = Result.From(error);
```
#### Result factory
Creates a `Result` 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
```csharp
// Returns `Result` with value
var result = Result.Create(
Array.Empty(),
() => new Model());
// Returns `Result` with errors
var result = Result.Create(
new List { Error.Failure("property", "code", "description") },
() => new Model());
```
### Extensions
#### Handling errors
```csharp
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 predicate);
IError error = result.LastError();
IError error = result.LastOrDefaultError();
IError error = result.LastOrDefaultError(Func predicate);
IError error = result.SingleError();
IError error = result.SingleOrDefaultError();
IError error = result.SingleOrDefaultError(Func predicate);
bool IResult.ContainsError();
bool IResult.ContainsError(Func predicate);
```
#### OfTypeFirstError
```csharp
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 result = Error.Forbidden("property", "code", "description");
var type = result.GetType(); // ForbiddenError
var model = new Model();
Result result = model;
var type = result.GetType(); // Model
```
#### Handling success
```csharp
bool IResult.IsSuccess();
bool IResult.IsSuccess(Func predicate);
```
#### Switch
```csharp
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));
```
#### Match
```csharp
TOutput response = result.Match(
value => onSuccess(value),
errors => onErrors(errors));
// Only return the value or first erro
TOutput response = result.MatchFirst(
value => onSuccess(value),
error => onError(error));
Task response = result.MatchAsync(
value => onSuccess(value),
errors => onErrors(errors));
// Only return the value or first erro
Task response = result.MatchFirstAsync(
value => onSuccess(value),
error => onError(error));
```
#### Conversions
```csharp
var errorList = result.Errors.AsList();
```
#### DistinctErrors
```csharp
Result result = new IError[]
{
Error.Conflict("FakeProperty", "FakeCode", "FakeDescription"),
Error.Conflict("FakeProperty", "FakeCode", "FakeDescription")};
// Only returns one error
var errors = result.DistinctErrors();
```
### Deconstruct operators
```csharp
var (property, code, description) = Error.Unauthorized("property", "code", "description");
Result result = new Model { Id = id, Name = name };
// Deconstruct -> value is not null and errors is empty
(var value, var errors) = result;
```
### Implicit conversion
```csharp
Result result = new Model { Id = id, Name = name };
Model model = result;
// Result with errors
Result result = Error.Conflict("property", "code", "description");
List errors = result;
```
### Check validity
**Valid example**
```csharp
Result 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**
```csharp
Result result = Error.Conflict("property", "code", "description");
// result = implicit conversion "false"
if(result)
{
// Do something
}
// Equivalent to
if(result.IsError == true)
{
// Do something
}
```
### Serialization/Deserialization
#### Results
**Serialization `Result` success example**
```csharp
var result = Result.Success();
var json = JsonSerializer.Serialize(result);
/*
json = {
"IsSuccess": true
}
*/
```
```csharp
var result = Result.Success(45);
var json = JsonSerializer.Serialize(result);
/*
json = {
"IsSuccess": true,
"Value": 45
}
*/
```
**Serialization `Result` errors example**
```csharp
Result result = Error.NotFound("client", "NOT_FOUND", "Client not found");
Result 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**
```csharp
var json = """
"IsSuccess": true
""";
var result = JsonSerializer.Deserialize(json);
```
```csharp
var json = """
"IsSuccess": true,
"Value": 541.7
""";
var result = JsonSerializer.Deserialize>(json);
```
**Deserialization `Result` errors example**
```csharp
var json = """
"IsSuccess": false,
"Errors": [
{
"_type": "PowerUtils.Results.NotFoundError",
"Property": "client",
"Code": "NOT_FOUND",
"Description":"Client not found"
}
]
""";
var result = JsonSerializer.Deserialize(json);
var result = JsonSerializer.Deserialize>(json);
```
#### Errors
**Serialization example**
```csharp
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**
```csharp
var json = """
{
"_type": "PowerUtils.Results.NotFoundError",
"Property": "client",
"Code": "NOT_FOUND",
"Description": "Client not found"
}
""";
var error = JsonSerializer.Deserialize(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`.
```csharp
var error = JsonSerializer.Deserialize(json);
```
**Custom error Serialization/Deserialization example**
```csharp
[JsonConverter(typeof(ErrorJsonConverter))]
public class CustomError : IError { }
```
## Contribution
If you have any questions, comments, or suggestions, please open an [issue](https://github.com/TechNobre/PowerUtils.Results/issues/new/choose) or create a [pull request](https://github.com/TechNobre/PowerUtils.Results/compare)