From fa618a9c934b0338788138951f8a4d524b2aeb3a Mon Sep 17 00:00:00 2001 From: Daniil Date: Mon, 6 May 2024 23:39:01 +0300 Subject: [PATCH 1/2] feat: add NoContent (204) status code support --- src/Ardalis.Result.AspNetCore/ResultStatusMap.cs | 3 ++- src/Ardalis.Result/Result.Void.cs | 9 +++++++++ src/Ardalis.Result/Result.cs | 15 +++++++++++++-- src/Ardalis.Result/ResultExtensions.cs | 1 + src/Ardalis.Result/ResultStatus.cs | 1 + 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Ardalis.Result.AspNetCore/ResultStatusMap.cs b/src/Ardalis.Result.AspNetCore/ResultStatusMap.cs index 038aa56..27d389a 100644 --- a/src/Ardalis.Result.AspNetCore/ResultStatusMap.cs +++ b/src/Ardalis.Result.AspNetCore/ResultStatusMap.cs @@ -41,7 +41,8 @@ public ResultStatusMap AddDefaultMap() .With(CriticalEntity)) .For(ResultStatus.Unavailable, HttpStatusCode.ServiceUnavailable, resultStatusOptions => resultStatusOptions - .With(UnavailableEntity)); + .With(UnavailableEntity)) + .For(ResultStatus.NoContent, HttpStatusCode.NoContent); } /// diff --git a/src/Ardalis.Result/Result.Void.cs b/src/Ardalis.Result/Result.Void.cs index 7a9d4dc..3a1bd86 100644 --- a/src/Ardalis.Result/Result.Void.cs +++ b/src/Ardalis.Result/Result.Void.cs @@ -193,5 +193,14 @@ public static Result ErrorWithCorrelationId(string correlationId, params string[ { return new Result(ResultStatus.CriticalError) { Errors = errorMessages }; } + + /// + /// Represents a situation where the server has successfully fulfilled the request, but there is no content to send back in the response body. + /// + /// A Result object + public new static Result NoContent() + { + return new Result(ResultStatus.NoContent); + } } } diff --git a/src/Ardalis.Result/Result.cs b/src/Ardalis.Result/Result.cs index b85611c..163f1a5 100644 --- a/src/Ardalis.Result/Result.cs +++ b/src/Ardalis.Result/Result.cs @@ -42,7 +42,7 @@ protected Result(ResultStatus status) public Type ValueType => typeof(T); [JsonInclude] public ResultStatus Status { get; protected set; } = ResultStatus.Ok; - public bool IsSuccess => Status == ResultStatus.Ok; + public bool IsSuccess => Status is ResultStatus.Ok or ResultStatus.NoContent; [JsonInclude] public string SuccessMessage { get; protected set; } = string.Empty; [JsonInclude] @@ -130,7 +130,8 @@ public static Result Invalid(ValidationError validationError) /// A Result public static Result Invalid(params ValidationError[] validationErrors) { - return new Result(ResultStatus.Invalid) { ValidationErrors = new List(validationErrors) }; + return new Result(ResultStatus.Invalid) + { ValidationErrors = new List(validationErrors) }; } /// @@ -230,5 +231,15 @@ public static Result Unavailable(params string[] errorMessages) { return new Result(ResultStatus.Unavailable) { Errors = errorMessages}; } + + /// + /// Represents a situation where the server has successfully fulfilled the request, but there is no content to send back in the response body. + /// + /// The type parameter representing the expected response data. + /// A Result object + public static Result NoContent() + { + return new Result(ResultStatus.NoContent); + } } } diff --git a/src/Ardalis.Result/ResultExtensions.cs b/src/Ardalis.Result/ResultExtensions.cs index 6a27793..f954efa 100644 --- a/src/Ardalis.Result/ResultExtensions.cs +++ b/src/Ardalis.Result/ResultExtensions.cs @@ -31,6 +31,7 @@ public static Result Map(this Result.Conflict(); case ResultStatus.CriticalError: return Result.CriticalError(result.Errors.ToArray()); case ResultStatus.Unavailable: return Result.Unavailable(result.Errors.ToArray()); + case ResultStatus.NoContent: return Result.NoContent(); default: throw new NotSupportedException($"Result {result.Status} conversion is not supported."); } diff --git a/src/Ardalis.Result/ResultStatus.cs b/src/Ardalis.Result/ResultStatus.cs index 750a06e..4317304 100644 --- a/src/Ardalis.Result/ResultStatus.cs +++ b/src/Ardalis.Result/ResultStatus.cs @@ -8,6 +8,7 @@ public enum ResultStatus Unauthorized, Invalid, NotFound, + NoContent, Conflict, CriticalError, Unavailable From 6c0089bae8f3ba4d564a2fbcd097f10ce054068e Mon Sep 17 00:00:00 2001 From: Daniil Date: Mon, 6 May 2024 23:49:42 +0300 Subject: [PATCH 2/2] test: add unit tests for no content status --- tests/Ardalis.Result.UnitTests/ResultConstructor.cs | 8 ++++++++ tests/Ardalis.Result.UnitTests/ResultMap.cs | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/tests/Ardalis.Result.UnitTests/ResultConstructor.cs b/tests/Ardalis.Result.UnitTests/ResultConstructor.cs index f695c56..b7b22c1 100644 --- a/tests/Ardalis.Result.UnitTests/ResultConstructor.cs +++ b/tests/Ardalis.Result.UnitTests/ResultConstructor.cs @@ -257,4 +257,12 @@ public void InitializedIsSuccessFalseForCriticalErrorFactoryCall() Assert.False(result.IsSuccess); } + + [Fact] + public void InitializesStatusToNoContentForNoContentFactoryCall() + { + var result = Result.NoContent(); + + Assert.True(result.IsSuccess); + } } diff --git a/tests/Ardalis.Result.UnitTests/ResultMap.cs b/tests/Ardalis.Result.UnitTests/ResultMap.cs index 696c2ff..56bc0d0 100644 --- a/tests/Ardalis.Result.UnitTests/ResultMap.cs +++ b/tests/Ardalis.Result.UnitTests/ResultMap.cs @@ -188,6 +188,19 @@ public void ShouldProduceCriticalErrorWithError() actual.Errors.Single().Should().Be(expectedMessage); } + [Fact] + public void ShouldProductNoContentWithoutAnyContent() + { + var result = Result.NoContent(); + + var actual = result.Map(val => val.ToString()); + + actual.Status.Should().Be(ResultStatus.NoContent); + actual.Value.Should().BeNull(); + actual.Errors.Should().BeEmpty(); + actual.ValidationErrors.Should().BeEmpty(); + } + private record Foo(string Bar); private class FooDto