Elephant.Types.Results
1.1.0
dotnet add package Elephant.Types.Results --version 1.1.0
NuGet\Install-Package Elephant.Types.Results -Version 1.1.0
<PackageReference Include="Elephant.Types.Results" Version="1.1.0" />
<PackageVersion Include="Elephant.Types.Results" Version="1.1.0" />
<PackageReference Include="Elephant.Types.Results" />
paket add Elephant.Types.Results --version 1.1.0
#r "nuget: Elephant.Types.Results, 1.1.0"
#:package Elephant.Types.Results@1.1.0
#addin nuget:?package=Elephant.Types.Results&version=1.1.0
#tool nuget:?package=Elephant.Types.Results&version=1.1.0
About
Continuation of my older ResponseWrappers from the Elephant.Types . I renamed it to Result because its much shorter and made a variety of improvements.
Why use the result pattern
There are really many reasons that can be found online. I'll highlight the 3 that I personally find the most important:
- Better performance. than exceptions.
- I don't like throwing exceptions for something that is expected.
- In some situations (e.x. n-tier) you don't want to be dealing with HTTP status codes in your data access- and business logic layers.
Installation
Choose one:
Package Manager (Visual Studio GUI)
- Right-click your project → "Manage NuGet Packages".
- Search for
Elephant.Types.Results. - Click "Install".
.NET CLI (Command Line)
dotnet add package Elephant.Types.Results
PackageReference (Project File)
<PackageReference Include="Elephant.Types.Results" Version="x.x.x" />
Package Manager (CLI)
nuget install Elephant.Types.Results
How to Use
Usage examples
With data
public async Task<IResult<Customer>> UpdateCustomerAsync(Customer customer, CancellationToken cancellationToken)
{
// Update customer logic here.
return Result<Customer>.Ok(updatedCustomer, "Optional message here.");
}
Without data
public async Task<IResult> UpdateCustomerAsync(Customer customer, CancellationToken cancellationToken)
{
Customer? customerInDb = _customerRepository.ById(customer.Id);
if (customerInDb == null)
return Result.NotFoundNoData();
// Update customer logic here.
}
public async Task<IResult> UpdateCustomerAsync(Customer customer, CancellationToken cancellationToken)
{
Customer? customerInDb = await _customerRepository.ByIdAsync(customer.Id);
if (customerInDb == null)
Result.NotFoundNoData($"{nameof(Customer)} with {nameof(Customer.Id)} {Customer.Id} not found.");
// Update customer logic here.
return Result.OkNoData();
}
Multi status support
private IResult<string> ErrorMethod(bool errorOccurred)
{
IResult<string> result = Result<string>.Ok("Success.");
if (errorOccurred)
{
// You can chain different statuses as long as the generic is of the same type.
// That means you can't combine the data and the no-data versions in the same chain because
// they have a different return type.
result.AddError("Error 1")
.AddInternalServerError("Error 2")
.AddContinue("Continue")
.AddOk("Ok data")
.AddConflict("Concurrency conflict on ..");
}
return result;
}
private IResult ChainNoDataMethod()
{
IResult result = Result.OkNoData();
result.AddErrorNoData("Unable to fetch cat food.")
.AddInternalServerErrorNoData("Unable to fetch cat food.")
.AddInternalServerErrorNoData()
.AddInternalServerErrorNoData("Unable to fetch cat food.")
.AddContinueNoData("Continue")
.AddConflictNoData("Concurrency conflict on ..");
return result;
}
Custom errors
return Result.ErrorNoData("Something went wrong.");
return Result<Customer>.Error(new YourCustomException(), 23122, customer); // With 23122 being your optional custom code.
Unwrap in controller
If you easily want to unwrap it in your controller, you may use the NuGet Elephant.ApiController version 3.0.0 or greater and then:
// Your attributes here.
MyController : ElephantControllerBase
{
[HttpPost]
[Route("customer-create-test")]
[ProducesResponseType(typeof(List<Customer>), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateCustomers(List<CustomerCreateRequestModel> requestModel, CancellationToken cancellationToken)
{
IResult<Customer> result = await _customerService.Create(requestModel, cancellationToken);
// Will return a 201 created response along with the created customers (assuming that your service returns them).
return Unwrap(result);
}
[HttpPost]
[Route("order-create-test")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateOrders(List<OrderCreateRequestModel> requestModel, CancellationToken cancellationToken)
{
IResult result = await _orderService.Create(requestModel, cancellationToken);
// Will return a 201 created response without any order data.
return Unwrap(result);
}
}
Other
You can override Result.GetResultStatus if for example you want to prioritize different statuses using custom logic.
You can create custom statuses as long as you derive from IResultStatus.
You can also override the success, error, informative and custom status checks in the ResultStatus class. This way you can create custom errors and successes and etc.
Contributing
Contributions are welcome. Please read our CONTRIBUTING.md file for guidelines on how to proceed.
License
This project is licensed under the MIT License. See the LICENSE.txt file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Elephant.Types.Results.Abstractions (>= 1.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Elephant.Types.Results:
| Package | Downloads |
|---|---|
|
Elephant.Database
Common EF Core database code. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Bugfix: Result.InternalServerError should use its parameter.