Skip to content

Commit

Permalink
Add support for HttpStatusCode: Created to the ResultStatus mapping (#…
Browse files Browse the repository at this point in the history
…198)

* Add support for mapping Result.Created to a Created ActionResult with setting of the location header

* Add Result constructor tests

---------

Co-authored-by: William Tyler Gibbons <[email protected]>
Co-authored-by: Steve Smith <[email protected]>
  • Loading branch information
3 people authored Sep 11, 2024
1 parent 67787ee commit ed54e92
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 1 deletion.
13 changes: 13 additions & 0 deletions sample/Ardalis.Result.Sample.Core/Services/WeatherService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ public Result<IEnumerable<WeatherForecast>> GetForecast(ForecastRequestDto model
ErrorMessage = "PostalCode is required" }
});
}

// Test value to return Created result with a location
if (model.PostalCode == "12345")
{
return Result<IEnumerable<WeatherForecast>>.Created(
Enumerable.Range(1, 1).Select(index =>
new WeatherForecast
{
Date = DateTime.Now,
TemperatureC = 0,
Summary = Summaries[0]
}), "weatherforecast/12345");
}

// test value
if (model.PostalCode == "55555")
Expand Down
11 changes: 11 additions & 0 deletions src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ internal static ActionResult ToActionResult(this ControllerBase controller, IRes
return typeof(Result).IsInstanceOfType(result)
? (ActionResult)controller.StatusCode(statusCode)
: controller.StatusCode(statusCode, result.GetValue());
case ResultStatus.Created:
if(string.IsNullOrEmpty(result.Location))
return controller.Created((string?)null, result.GetValue());

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 79 in src/Ardalis.Result.AspNetCore/ActionResultExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

var httpRequest = controller.HttpContext.Request;
var locationUri = new UriBuilder(httpRequest.Scheme,
httpRequest.Host.Host,
httpRequest.Host.Port ?? -1,
result.Location).Uri.AbsoluteUri;

return controller.Created(locationUri, result.GetValue());
default:
return resultStatusOptions.ResponseType == null
? (ActionResult)controller.StatusCode(statusCode)
Expand Down
3 changes: 2 additions & 1 deletion src/Ardalis.Result.AspNetCore/ResultConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ So we should avoid pairing 'void' Result with OK or Created

var resultStatuses = attr?.ResultStatuses ?? _map.Keys;

foreach (var status in resultStatuses.Where(s => s != ResultStatus.Ok))
foreach (var status in resultStatuses.Where(s =>
s is not (ResultStatus.Ok or ResultStatus.Created)))
{
var info = _map[status];
AddProducesResponseTypeAttribute(action.Filters, (int)info.GetStatusCode(method), info.ResponseType);
Expand Down
1 change: 1 addition & 0 deletions src/Ardalis.Result.AspNetCore/ResultStatusMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ internal ResultStatusMap()
public ResultStatusMap AddDefaultMap()
{
return For(ResultStatus.Ok, HttpStatusCode.OK)
.For(ResultStatus.Created, HttpStatusCode.Created)
.For(ResultStatus.Error, (HttpStatusCode)422, resultStatusOptions => resultStatusOptions
.With(UnprocessableEntity))
.For(ResultStatus.Forbidden, HttpStatusCode.Forbidden)
Expand Down
1 change: 1 addition & 0 deletions src/Ardalis.Result/IResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ public interface IResult
IEnumerable<ValidationError> ValidationErrors { get; }
Type ValueType { get; }
object GetValue();
string Location { get; }
}
}
16 changes: 16 additions & 0 deletions tests/Ardalis.Result.UnitTests/ResultConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,4 +345,20 @@ public void InitializesStatusToNoContentForNoContentFactoryCall()

Assert.True(result.IsSuccess);
}

[Fact]
public void InitializedIsSuccessTrueForCreatedFactoryCall()
{
var result = Result<object>.Created(new object());

Assert.True(result.IsSuccess);
}

[Fact]
public void InitializedIsSuccessTrueForCreatedWithLocationFactoryCall()
{
var result = Result<object>.Created(new object(), "sample/endpoint");

Assert.True(result.IsSuccess);
}
}

0 comments on commit ed54e92

Please sign in to comment.