Skip to content

Commit

Permalink
Add Result.NoContent support (HTTP 204) (#178)
Browse files Browse the repository at this point in the history
* feat: add NoContent (204) status code support

* test: add unit tests for no content status

---------

Co-authored-by: Steve Smith <steve@kentsmiths.com>
  • Loading branch information
dadyarri and ardalis authored May 13, 2024
1 parent 8f8f2df commit ddbac3f
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/Ardalis.Result.AspNetCore/ResultStatusMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/// <summary>
Expand Down
9 changes: 9 additions & 0 deletions src/Ardalis.Result/Result.Void.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,14 @@ public static Result ErrorWithCorrelationId(string correlationId, params string[
{
return new Result(ResultStatus.CriticalError) { Errors = errorMessages };
}

/// <summary>
/// Represents a situation where the server has successfully fulfilled the request, but there is no content to send back in the response body.
/// </summary>
/// <returns>A Result object</returns>
public new static Result NoContent()
{
return new Result(ResultStatus.NoContent);
}
}
}
16 changes: 14 additions & 2 deletions src/Ardalis.Result/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ protected Result(ResultStatus status)
[JsonInclude]
public ResultStatus Status { get; protected set; } = ResultStatus.Ok;

public bool IsSuccess => Status is ResultStatus.Ok or ResultStatus.Created;
public bool IsSuccess => Status is ResultStatus.Ok or ResultStatus.NoContent or ResultStatus.Created;

[JsonInclude]
public string SuccessMessage { get; protected set; } = string.Empty;
[JsonInclude]
Expand Down Expand Up @@ -156,7 +157,8 @@ public static Result<T> Invalid(ValidationError validationError)
/// <returns>A Result<typeparamref name="T"/></returns>
public static Result<T> Invalid(params ValidationError[] validationErrors)
{
return new Result<T>(ResultStatus.Invalid) { ValidationErrors = new List<ValidationError>(validationErrors) };
return new Result<T>(ResultStatus.Invalid)
{ ValidationErrors = new List<ValidationError>(validationErrors) };
}

/// <summary>
Expand Down Expand Up @@ -256,5 +258,15 @@ public static Result<T> Unavailable(params string[] errorMessages)
{
return new Result<T>(ResultStatus.Unavailable) { Errors = errorMessages};
}

/// <summary>
/// Represents a situation where the server has successfully fulfilled the request, but there is no content to send back in the response body.
/// </summary>
/// <typeparam name="T">The type parameter representing the expected response data.</typeparam>
/// <returns>A Result object</returns>
public static Result<T> NoContent()
{
return new Result<T>(ResultStatus.NoContent);
}
}
}
1 change: 1 addition & 0 deletions src/Ardalis.Result/ResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public static Result<TDestination> Map<TSource, TDestination>(this Result<TSourc
: Result<TDestination>.Conflict();
case ResultStatus.CriticalError: return Result<TDestination>.CriticalError(result.Errors.ToArray());
case ResultStatus.Unavailable: return Result<TDestination>.Unavailable(result.Errors.ToArray());
case ResultStatus.NoContent: return Result<TDestination>.NoContent();
default:
throw new NotSupportedException($"Result {result.Status} conversion is not supported.");
}
Expand Down
1 change: 1 addition & 0 deletions src/Ardalis.Result/ResultStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum ResultStatus
Unauthorized,
Invalid,
NotFound,
NoContent,
Conflict,
CriticalError,
Unavailable
Expand Down
8 changes: 8 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -284,4 +284,12 @@ public void InitializedIsSuccessFalseForCriticalErrorFactoryCall()

Assert.False(result.IsSuccess);
}

[Fact]
public void InitializesStatusToNoContentForNoContentFactoryCall()
{
var result = Result<object>.NoContent();

Assert.True(result.IsSuccess);
}
}
13 changes: 13 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,19 @@ public void ShouldProduceCriticalErrorWithError()
actual.Errors.Single().Should().Be(expectedMessage);
}

[Fact]
public void ShouldProductNoContentWithoutAnyContent()
{
var result = Result<int>.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
Expand Down

0 comments on commit ddbac3f

Please sign in to comment.