FluentResults icon indicating copy to clipboard operation
FluentResults copied to clipboard

success and errors message in result is empty

Open armanhadi1458 opened this issue 2 years ago • 3 comments

Hello im using fluent result version 3.5 with .net 6 api When I return the answer with Result.Ok<PersonDto>(person).WithSuccess("Operation Successfull ...") in swagger reasons are fill bu successe message are empty why?

222

when switch in fluent result version 2.6 everything ok

armanhadi1458 avatar May 21 '22 07:05 armanhadi1458

Hi, the truth is I don't know. In v3 I switched from base classes (Success and Error inherit from Reason) to interfaces (ISuccess and IError inherit from IReason). Maybe in your serialization library is a different behavior for interfaces.

BUT I highly recommend to use your own custom Result class for public apis like swagger endpoint. Why, see [Serializing Result objects (ASP.NET WebApi, Hangfire)](https://github.com/altmann/FluentResults#serializing-result-objects-aspnet-webapi-hangfire) You don't want that I can break your public api/swagger endpoints if I make changes in the public api of FluentResults and I think it makes not much sense that you sent douplicate information over the wire (IsSuccess, IsFailed, Reasons, Successes, ...).

I hope it makes sense for you.

altmann avatar Jun 06 '22 08:06 altmann

I have the same issue. So, yes having own Dto class makes sense. Someone uses ErrorCodes. We use in some cases "keys" to separate the message in specific part in frontend.

My idea is overwritting the JsonCoverter. This is useful, when you want to convert a specific class somehow. In our case we want to convert the Result class into ResultDto. The problem is, how can we provide the data? Do you have any idea? The advantage with this idea would be, I can simple return the Result class in each action. Here is my code:

public class ResultDto
        {
            public bool IsSuccess { get; set; }

            public IEnumerable<ErrorDto> Errors { get; set; }

            public ResultDto(bool isSuccess, IEnumerable<ErrorDto> errors)
            {
                IsSuccess = isSuccess;
                Errors = errors;
            }
        }

        public class ErrorDto
        {
            public string Message { get; set; }

            public string Key { get; set; }

            public ErrorDto(string message, string key)
            {
                Message = message;
                Key = key;
            }
        }

        public static class ResultDtoExtensions
        {
            public static ResultDto ToResultDto(this Result result)
            {
                if (result.IsSuccess)
                    return new ResultDto(true, Enumerable.Empty<ErrorDto>());

                return new ResultDto(false, TransformErrors(result.Errors));
            }

            private static IEnumerable<ErrorDto> TransformErrors(List<IError> errors)
            {
                return errors.Select(TransformError);
            }

            private static ErrorDto TransformError(IError error)
            {
                var errorCode = TransformErrorKey(error);

                return new ErrorDto(error.Message, errorCode);
            }

            private static string TransformErrorKey(IError error)
            {
                if (error.Metadata.TryGetValue("Key", out var key))
                    return key as string;

                return "";
            }
        }

    }

    public class ResultJsonConverter : JsonConverter<Result>
    {
        public override Result Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }

        public override void Write(Utf8JsonWriter writer, Result result, JsonSerializerOptions options)
        {
            result.ToResultDto();

            // Convert to Json 
            // ...
            // send ans String Value: writer.WriteStringValue(myJson);
        }
    }

Kingside88 avatar Jun 10 '22 22:06 Kingside88

Maybe an idea would be to use a middleware and not a custom JsonConverter for this task. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0 The middleware get hte result object and transform it to an ResultDto object.

altmann avatar Jun 13 '22 19:06 altmann

I plan to release a new package with aspnetcore integration in the next weeks. Follow #149 for more information.

altmann avatar Oct 10 '22 19:10 altmann