Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/Ardalis.Result.AspNetCore/MinimalApiResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#if NET7_0_OR_GREATER
namespace Ardalis.Result.AspNetCore;

public static partial class ResultExtensions
{
/// <summary>
Expand Down Expand Up @@ -33,14 +34,15 @@ internal static Microsoft.AspNetCore.Http.IResult ToMinimalApiResult(this IResul
result.Status switch
{
ResultStatus.Ok => typeof(Result).IsInstanceOfType(result)
? Results.Ok()
: Results.Ok(result.GetValue()),
? Results.Ok()
: Results.Ok(result.GetValue()),
ResultStatus.NotFound => NotFoundEntity(result),
ResultStatus.Unauthorized => Results.Unauthorized(),
ResultStatus.Forbidden => Results.Forbid(),
ResultStatus.Invalid => Results.BadRequest(result.ValidationErrors),
ResultStatus.Error => UnprocessableEntity(result),
ResultStatus.Conflict => ConflictEntity(result),
ResultStatus.CriticalError => CriticalEntity(result),
_ => throw new NotSupportedException($"Result {result.Status} conversion is not supported."),
};

Expand Down Expand Up @@ -76,7 +78,7 @@ private static Microsoft.AspNetCore.Http.IResult NotFoundEntity(IResult result)
return Results.NotFound();
}
}

private static Microsoft.AspNetCore.Http.IResult ConflictEntity(IResult result)
{
var details = new StringBuilder("Next error(s) occured:");
Expand All @@ -96,5 +98,26 @@ private static Microsoft.AspNetCore.Http.IResult ConflictEntity(IResult result)
return Results.Conflict();
}
}

private static Microsoft.AspNetCore.Http.IResult CriticalEntity(IResult result)
{
var details = new StringBuilder("Next error(s) occured:");

if (result.Errors.Any())
{
foreach (var error in result.Errors) details.Append("* ").Append(error).AppendLine();

return Results.Problem(new ProblemDetails()
{
Title = "Something went wrong.",
Detail = details.ToString(),
Status = StatusCodes.Status500InternalServerError
});
}
else
{
return Results.StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
#endif
12 changes: 12 additions & 0 deletions src/Ardalis.Result/Result.Void.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,17 @@ public static Result ErrorWithCorrelationId(string correlationId, params string[
{
return new Result(ResultStatus.Conflict) { Errors = errorMessages };
}

/// <summary>
/// Represents a critical error that occurred during the execution of the service.
/// Everything provided by the user was valid, but the service was unable to complete due to an exception.
/// See also HTTP 500 Internal Server Error: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_server_errors
/// </summary>
/// <param name="errorMessages">A list of string error messages.</param>
/// <returns>A Result</returns>
public static Result CriticalError(params string[] errorMessages)
{
return new Result(ResultStatus.CriticalError) { Errors = errorMessages };
}
}
}
8 changes: 8 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,12 @@ public void InitializedIsSuccessFalseForConflictFactoryCall()

result.IsSuccess.Should().BeFalse();
}

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

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

[Fact]
public void ShouldProduceCriticalErrorWithError()
{
string expectedMessage = "Some critical error";
var result = Result<int>.CriticalError(expectedMessage);

var actual = result.Map(val => val.ToString());

actual.Status.Should().Be(ResultStatus.CriticalError);
actual.Errors.Single().Should().Be(expectedMessage);
}

private record Foo(string Bar);

private class FooDto
Expand Down
11 changes: 11 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultVoidConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,15 @@ public void InitializesConflictResultWithFactoryMethodWithErrors()
result.Status.Should().Be(ResultStatus.Conflict);
result.Errors.Single().Should().Be(errorMessage);
}

[Fact]
public void InitializesCriticalErrorResultWithFactoryMethodWithErrors()
{
var errorMessage = "Some critical error";
var result = Result.CriticalError(errorMessage);

result.Value.Should().BeNull();
result.Status.Should().Be(ResultStatus.CriticalError);
result.Errors.Single().Should().Be(errorMessage);
}
}
11 changes: 11 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultVoidMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,16 @@ public void ShouldProduceConflict()
actual.Status.Should().Be(ResultStatus.Conflict);
actual.Value.Should().BeNull();
}

[Fact]
public void ShouldProduceCriticalError()
{
var result = Result.CriticalError();

var actual = result.Map(_ => "This should be ignored");

actual.Status.Should().Be(ResultStatus.CriticalError);
actual.Value.Should().BeNull();
}
}
}
9 changes: 9 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultVoidToResultOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,14 @@ public void ConvertFromConflictResultOfUnit()
result.Value.Should().BeNull();
}

[Fact]
public void ConvertFromCriticalErrorResultOfUnit()
{
var result = DoBusinessOperationExample<object>(Result.CriticalError());

result.Status.Should().Be(ResultStatus.CriticalError);
result.Value.Should().BeNull();
}

public Result<T> DoBusinessOperationExample<T>(Result testValue) => testValue;
}