altmann / fluentresults Goto Github PK
View Code? Open in Web Editor NEWA generalised Result object implementation for .NET/C#
License: MIT License
A generalised Result object implementation for .NET/C#
License: MIT License
It would be nice to add an abstraction to the 'Fail' to where developers can add error codes and more details around the error.
See Facebook error codes for example:
https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling
Personally, I use https://github.com/ardalis/SmartEnum Smart Enums for this usecase.
I would be able to pass this:
Result.Fail(EnumIsInsertedHere, optionalStringMessage)
Right now if I want to accomplish this I must create a new class inheriting from Result and modify the library.
I hope others will find this useful too.
The goal imo is to not throw exceptions, yet maintain a unified result model for methods. This allows us to work with API's and error messages easily.
Thanks!
Would not it be nice to have a function that can wrap any execution and return Result
instead with all the details nicely in an object rather than throwing an exception?
I've just started with the whole concept of Result objects, and currently trying to use them/learn how to use them in the old pet project of mine.
One thing that I found lacking is the method like .WithErrors, that would accept IEnumerable of either Error objects or error messages. Because there are few places where I already have error collection of some sort, and it would be convenient to attach it to the Result.
Currently I had to write an extension method:
public static class ResultExtensions
{
public static Result WithErrors(this Result result, IEnumerable<string> errorMessages)
{
foreach (var errorMessage in errorMessages)
{
result.WithError(errorMessage);
}
return result;
}
}
What are your thoughts on adding something similar to the library?
Or is there something I've missed?
First of all thank you for this wonderful library. It really save so much of time & effort
I am having a requirement like below. I have two nested methods. Both returning Result object
Result<bool> Method1()
{
var m2Result = Method2();
if (m2Result.IsSuccess)
{
//Do some other operations
return Results.Ok(true);
}
else
{
return Results.Fail<bool>(m2Result.Errors); //Here I need to pass the list of errors for tracking purpose. However, at present Fail accepts only one Error object
}
}
Result<int> Method2()
{
}
This is the problem I am currently facing. Hope my understanding about this library is correct. Or, can we achieve the same by someother means? If not, would it be possible to include this functionality?
Thanks in advance
Regards
Athi
When I finish all my operations and get the results, I want to display some logs. I wonder, how am I able to log information about the exception that is attached to a given Error
? I see that the only property that I am able to access is Message
.
Review the readme and correct to better english.
Hi,
first, thank you for your great work. We're using your library and we'd like to know what is the best way to handle Error?
For example at one point we return a failure:
return Results.Fail(new MoResourceNotFoundError(entityIdentifier.Id));
Now, handling (catching) it is a bit "unfriendly":
if (moSetupResponse.Errors.Any(x => x is MoResourceNotFoundError)
Maybe I'm missing some helper function?
Alternative is throwing/catching exceptions, but we'd like to avoid that here.
IEnumerable<Result> results = new List<Result>();
Result mergedResult = results.Merge();
IEnumerable<Result<int>> results = new List<Result<int>>();
Result<IEnumerable<int>> mergedResult = results.Merge();
Hello!
Can you please add license information to this project. Is it MIT?
Thanks!
Set constructor to deprecated.
Great job!
Remove Custom Results from documentation because it is not necessary any more
Would it be suitable to add a ToResult<T>(T value)
option? Currently, when using the ToResult it is just using the default value, or the converter is supplied. For a scenario I have, I would like something other than the default. e.g.,
public Result<bool> DoStuff()
{
if (something)
{
Result fooResult = Foo();
return fooResult.ToResult(true);
}
return Result.Ok(false);
}
I have currently worked round this by doing fooResult.ToResult<bool>().WithValue(true)
. The implementation would be something like:
public Result<TNewValue> ToResult<TNewValue>(TNewValue newValue)
{
return new Result<TNewValue>()
.WithReasons(Reasons)
.WithValue(newValue);
}
@JasonLandbridge wrote originally here
Also, I'm probably the biggest fan of FluentResults ever because I'm making a Typescript version of FluentResults as we speak, with the same syntax so it should work 1 on 1. It's called FluentTypeResults and I have just finished converting everything to Typescript, and now I will test it out in my own project.
The idea behind is to have my .NET Core WebApi always return a Fluent Result. And then in my Vue.js/Typescript front-end cast the API response to a Typescript Result and from there check if there are any errors which I would like to show to the user :D
Let me know is this is good or bad practice because I couldn't find any articles or resources on this.
Only push and publishing a new version is now open - OkIf(...) FailIf(...) added.
I am looking to use this library as a way to handle various different fail states that may occur in an Asp.Net API I am working on.
It's very rough at present, but essentially, I want to expose extension methods like:
public static Result Forbid(this Result result, string message = "Forbidden!")
{
return result.WithError(new HttpError<string>(HttpResponseCode.Forbidden, message));
}
Would you be interested in this here, or not at all?
Consider best practices from ms:
https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/cross-platform-targeting
@stefandevo mentioned in PR #1 that he want to be able to add the name of the field to errors.
I want to solve this in a more generic way: There is a property MetaInfo property at the Reason class which can store some meta info, e.g. the field name.
This library looks like it would be very helpful for a project I manage, however I can't get it working.
The project is a C# WebAPI (REST service) project being developed in Visual Studio 2017 (Enterprise Edition) and targets the 4.7.2 version of the .NET Framework. I installed version 1.6.0 of FluentResults using the NuGet Package Manager built into VS.
In order to just test it quickly I looked at some of the unit tests in the GitHub repository (specifically, the ResultWithValueTests.cs file) and tried adding the following line in a method:
c# var okResult = FluentResults.Result.Ok(5);
This was taken from line 35 of the ResultWithValueTests.cs file. But the above line causes an error which states:
'Result' does not contain a definition for 'Ok'
and the code of the error is CS0117.
I tried clone the FluentResults repository directly from GitHub through VS 2017 and it works fine. The line does have any problem, but when I try it in my own project.
If anyone has any idea or suggestions on why I a getting this error or what a possible solution is, I would greatly appreciate it. This library seems like it would help streamline a lot of things in my project, but I can't even get a single line of code to work.
Thank you in advance for any assistance.
Add property in csproj
Target: Nuget users should be able to navigate from the nuget page https://www.nuget.org/packages/FluentResults/ directly to the github page https://github.com/altmann/FluentResults
Hi there,
First off, this is a great library and I'm a big fan of it!
I initially followed this article but instead of reinventing the wheel I started using FluentResults in my Fluent Validation pipeline. Basically all responses coming from my CQRS Queries are wrapped in the Result object, this avoids having to work with exceptions as a method of error handeling.
However, I can't get my pipeline to play nice:
public class ValidationPipeline<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TResponse : class
where TRequest : IRequest<TResponse>
{
private readonly IValidator<TRequest> _compositeValidator;
public ValidationPipeline(IValidator<TRequest> compositeValidator)
{
_compositeValidator = compositeValidator;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var result = await _compositeValidator.ValidateAsync(request, cancellationToken);
if (!result.IsValid)
{
Error error = new Error();
var responseType = typeof(TResponse);
foreach (var validationFailure in result.Errors)
{
Log.Warning($"{responseType} - {validationFailure.ErrorMessage}");
error.Reasons.Add(new Error(validationFailure.ErrorMessage));
}
// This always returns null instead of a Result with errors in it.
var f = Result.Fail(error) as TResponse;
return f;
// This causes an exception saying it cannot find the constructor.
var invalidResponse =
Activator.CreateInstance(invalidResponseType, null) as TResponse;
}
return await next();
}
}
I also have to somehow convert the Result object back to TResponse, where TResponse is always a Result
Any suggestions are greatly appreciated!
Edit: Could the Result constructor be made public instead of internal?
How can I use a PagedList
with your library?
public class PagedList<T> : List<T>
{
public int CurrentPage { get; private set; }
public int TotalPages { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public bool HasPrevious => CurrentPage > 1;
public bool HasNext => CurrentPage < TotalPages;
public PagedList(List<T> items, int count, int pageNumber, int pageSize)
{
TotalCount = count;
PageSize = pageSize;
CurrentPage = pageNumber;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
AddRange(items);
}
public static PagedList<T> ToPagedList(IQueryable<T> source, int pageNumber, int pageSize)
{
var count = source.Count();
var items = source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
return new PagedList<T>(items, count, pageNumber, pageSize);
}
}
Is this Ok?
var obj = myList.AsQueryable().ToPagedList(4, 1);
Result<PagedList<MyCustomObject>> x = Result.Ok(obj); // HERE
Custom Results (not using Value property, but a custom named property) seems like a good idea to make the Value property more descriptive. In reality it was not used. Best practice is to name the function descriptive which returns a result object and also think about naming the result object correctly.
So the idea is to remove Custom Results and make the code base smaller to be more flexible for other features.
Would you consider an implicit operator from Result<TValue>
to TValue
which would return a succeeded result?
Hello all,
I am encountering what appears to be a bug.
GOAL:
In some methods, I want to return a Result such as "User", so I query the User, and the User is wrapped by a Results object.
I see in the demo code, that you can wrap an Object like this:
In my code, when I do this, I get the error:
Result is in status failed. Value is not set.
and Result.Value
appears to throw an excpetion.
I get the same error when I do any of the following combinations (these are not in the demo code, I was just problem solving and trying to find a working @scenerio)
Result.Fail<AeonicProxyDto>("This is the error message explaining details of why it failed...").ToResult();
Result.Fail<AeonicProxyDto>("This is the error message explaining details of why it failed...").ToResult<AeonicProxyDto>()
Result.Fail("This is the error message explaining details of why it failed...").ToResult<AeonicProxyDto>();
From what I can see, my code is the same as the examples. If I remove the from the Results<Object>
making it like Result
instead, the method throws an error, and I must also remove the from the method. This prevents me from returning the User
Object.
326 stars on this repository, it looks great! I can't imagine this is a bug with that many stars, but with that said I do not know what I am doing wrong.
Can someone please advise?
Here the list of ressources:
Just started using the library to refactor some existing code I have. I have a common scenario that has I have come across that I keep having to do something like:
public Result<Foo> GetTheFoos()
{
Result<Bar> barsResult = GetTheBars();
if (barsResult.IsFailed)
{
return barsResult.ToResult<Foo>();
}
return ConvertBarsToFoos(barsResult.Value);
}
Basically, I’m trying to come up with a way of shortcutting this, similar to the OkIf and FailIf methods, something like:
public Result<Foo> GetTheFoos()
{
Result<Bar> barsResult = GetTheBars();
return Result.FailIf<Foo>(barsResult, () => ConvertBarsToFoos(barsResult.Value));
}
Would these be suitable extensions to add? Do have you any better ideas?
How do I achieve something like this in the new version?
return Results<GetPaymentLogsQueryResult>.Ok()
.WithSuccess($"Retrieved Payment logs successfully")
.With(res =>
{
res.AuditLogs = logs.ToArray();
});
public class GetPaymentLogsQueryResult : ResultBase<GetPaymentLogsQueryResult>
{
public Domain.Model.PaymentAuditLog[] AuditLogs { get; internal set; }
public GetPaymentLogsQueryResult()
{
}
}
I'm currently working on a new project in which we use the FluentResults library a lot.
One of the shortcomings I see is the amount of boilerplate one has to write when working with typed error objects. Immediately I thought, this would be a perfect usecase for records.
Instead of having to write something like
public class InvalidIdError : Error {
public InvalidIdError(int id)
{
Id = id;;
}
public int Id{ get; }
}
this would reduce to
public record InvalidIdError(int Id) : Error { }
So this proposal is probably more of a question, if you have already thought about that, and why it would be a good idea or not.
This would obviously lead to a major breaking change in the API, as existing derivations would have to be rewritten to records, but I think from a QoL perspective it could be an interesting way to go.
Hi there,
Is there a clean way to use the Result Errors in a Fluent Assertions type of way.
As an example:
createResult.IsFailed.Should().BeFalse(createResult.Errors.ToString());
This outputs something like:
Expected createResult.IsFailed to be false because System.Collections.Generic.List`1[FluentResults.Error], but found True.
My suggestion would be something like:
createResult.IsFailed.Should().BeFalse(createResult.ErrorString);
Which outputs something like:
Expected createResult.IsFailed to be false because due to "'Height' must be greater than '0', 'Width' must be greater than '0'" and "'Size' must be greater than '0'", but found True.
I understand the need to not create a dependency on the FluentAssertion package but otherwise an extension method would make it even more easy to use.
Such as:
createResult.ShouldBeValid();
Which throws an exception outputting the errors.
Thanks in advance!
Make a new release and publish it to NuGet.
Unfortunately when working with Asp.Net and Microsoft.Extensions.Logging constantly need set "using ILogger = Microsoft.Extensions.Logging.ILogger" because there is a match by name.
Would you consider this suggestion and rename or move ILogger?
First of all, I want to say, that it is a cool and simple library, which can help to up code readability.
But I faced with undesirable behavior (at least in some situations). Sometimes, throwing an exception when accessing Value is not desirable behavior when the Result is failed.
Let me describe my case:
I have method when I enumerate some lists and do some actions with items. As method output, I want to get a list of successfully processed items in Result.Value, and Failures in Failures list. I don't stop the flow if I have some failures, just log it in at the end.
I agree, that IsFailed/IsSuccess flags should depend on the existence of Failures, but what the reason to force block get/set Value?
Hello!
I would love to contribute to the project, I am wondering where @altmann you think time should be spent. Do you have a list of priorities for features? Such as:
ToDo
list of features which need to be implementedWishlist of Enhancements
which would be nice to have added to the library?Thanks for the awesome library!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.