Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CreatedResult should accept null location #42576

Merged
merged 8 commits into from
Dec 8, 2022
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
24 changes: 11 additions & 13 deletions src/Http/Http.Results/src/Created.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public sealed class Created : IResult, IEndpointMetadataProvider, IStatusCodeHtt
/// provided.
/// </summary>
/// <param name="location">The location at which the content has been created.</param>
internal Created(string location)
internal Created(string? location)
{
Location = location;
}
Expand All @@ -30,20 +30,18 @@ internal Created(string location)
/// provided.
/// </summary>
/// <param name="locationUri">The location at which the content has been created.</param>
internal Created(Uri locationUri)
internal Created(Uri? locationUri)
{
if (locationUri == null)
if (locationUri != null)
{
throw new ArgumentNullException(nameof(locationUri));
}

if (locationUri.IsAbsoluteUri)
{
Location = locationUri.AbsoluteUri;
}
else
{
Location = locationUri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
if (locationUri.IsAbsoluteUri)
{
Location = locationUri.AbsoluteUri;
}
else
{
Location = locationUri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
}
}
}

Expand Down
24 changes: 11 additions & 13 deletions src/Http/Http.Results/src/CreatedOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public sealed class Created<TValue> : IResult, IEndpointMetadataProvider, IStatu
/// </summary>
/// <param name="location">The location at which the content has been created.</param>
/// <param name="value">The value to format in the entity body.</param>
internal Created(string location, TValue? value)
internal Created(string? location, TValue? value)
{
Value = value;
Location = location;
Expand All @@ -35,23 +35,21 @@ internal Created(string location, TValue? value)
/// </summary>
/// <param name="locationUri">The location at which the content has been created.</param>
/// <param name="value">The value to format in the entity body.</param>
internal Created(Uri locationUri, TValue? value)
internal Created(Uri? locationUri, TValue? value)
{
Value = value;
HttpResultsHelper.ApplyProblemDetailsDefaultsIfNeeded(Value, StatusCode);

if (locationUri == null)
if (locationUri != null)
{
throw new ArgumentNullException(nameof(locationUri));
}

if (locationUri.IsAbsoluteUri)
{
Location = locationUri.AbsoluteUri;
}
else
{
Location = locationUri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
if (locationUri.IsAbsoluteUri)
{
Location = locationUri.AbsoluteUri;
}
else
{
Location = locationUri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
}
}
}

Expand Down
18 changes: 12 additions & 6 deletions src/Http/Http.Results/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,13 @@ static Microsoft.AspNetCore.Http.Results.Content(string? content, Microsoft.Net.
static Microsoft.AspNetCore.Http.Results.Content(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Content(string? content, string? contentType, System.Text.Encoding? contentEncoding) -> Microsoft.AspNetCore.Http.IResult!
*REMOVED*static Microsoft.AspNetCore.Http.Results.Text(string! content, string? contentType = null, System.Text.Encoding? contentEncoding = null) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created<TValue>(System.Uri! uri, TValue? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created<TValue>(string! uri, TValue? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created() -> Microsoft.AspNetCore.Http.IResult!
*REMOVED*static Microsoft.AspNetCore.Http.Results.Created(string! uri, object? value) -> Microsoft.AspNetCore.Http.IResult!
*REMOVED*static Microsoft.AspNetCore.Http.Results.Created(System.Uri! uri, object? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created(string? uri, object? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created(System.Uri? uri, object? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created<TValue>(string? uri, TValue? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Created<TValue>(System.Uri? uri, TValue? value) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.CreatedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default(TValue?)) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.Json<TValue>(TValue? data, System.Text.Json.JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.Results.NotFound<TValue>(TValue? value) -> Microsoft.AspNetCore.Http.IResult!
Expand All @@ -171,6 +176,11 @@ static Microsoft.AspNetCore.Http.Results.Text(System.ReadOnlySpan<byte> utf8Cont
static Microsoft.AspNetCore.Http.Results.UnprocessableEntity<TValue>(TValue? error) -> Microsoft.AspNetCore.Http.IResult!
static Microsoft.AspNetCore.Http.TypedResults.Content(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
static Microsoft.AspNetCore.Http.TypedResults.Content(string? content, string? contentType, System.Text.Encoding? contentEncoding) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
static Microsoft.AspNetCore.Http.TypedResults.Created() -> Microsoft.AspNetCore.Http.HttpResults.Created!
static Microsoft.AspNetCore.Http.TypedResults.Created(string? uri) -> Microsoft.AspNetCore.Http.HttpResults.Created!
static Microsoft.AspNetCore.Http.TypedResults.Created(System.Uri? uri) -> Microsoft.AspNetCore.Http.HttpResults.Created!
static Microsoft.AspNetCore.Http.TypedResults.Created<TValue>(string? uri, TValue? value) -> Microsoft.AspNetCore.Http.HttpResults.Created<TValue>!
static Microsoft.AspNetCore.Http.TypedResults.Created<TValue>(System.Uri? uri, TValue? value) -> Microsoft.AspNetCore.Http.HttpResults.Created<TValue>!
static Microsoft.AspNetCore.Http.TypedResults.Text(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
static Microsoft.AspNetCore.Http.TypedResults.Text(string? content, string? contentType, System.Text.Encoding? contentEncoding) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
static Microsoft.AspNetCore.Http.TypedResults.Text(System.ReadOnlySpan<byte> utf8Content, string? contentType = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.HttpResults.Utf8ContentHttpResult!
Expand Down Expand Up @@ -243,10 +253,6 @@ static Microsoft.AspNetCore.Http.TypedResults.Challenge(Microsoft.AspNetCore.Aut
static Microsoft.AspNetCore.Http.TypedResults.Conflict() -> Microsoft.AspNetCore.Http.HttpResults.Conflict!
static Microsoft.AspNetCore.Http.TypedResults.Conflict<TValue>(TValue? error) -> Microsoft.AspNetCore.Http.HttpResults.Conflict<TValue>!
static Microsoft.AspNetCore.Http.TypedResults.Content(string? content, Microsoft.Net.Http.Headers.MediaTypeHeaderValue! contentType) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
static Microsoft.AspNetCore.Http.TypedResults.Created(System.Uri! uri) -> Microsoft.AspNetCore.Http.HttpResults.Created!
static Microsoft.AspNetCore.Http.TypedResults.Created(string! uri) -> Microsoft.AspNetCore.Http.HttpResults.Created!
static Microsoft.AspNetCore.Http.TypedResults.Created<TValue>(System.Uri! uri, TValue? value) -> Microsoft.AspNetCore.Http.HttpResults.Created<TValue>!
static Microsoft.AspNetCore.Http.TypedResults.Created<TValue>(string! uri, TValue? value) -> Microsoft.AspNetCore.Http.HttpResults.Created<TValue>!
static Microsoft.AspNetCore.Http.TypedResults.CreatedAtRoute(string? routeName = null, object? routeValues = null) -> Microsoft.AspNetCore.Http.HttpResults.CreatedAtRoute!
static Microsoft.AspNetCore.Http.TypedResults.CreatedAtRoute<TValue>(TValue? value, string? routeName = null, object? routeValues = null) -> Microsoft.AspNetCore.Http.HttpResults.CreatedAtRoute<TValue>!
static Microsoft.AspNetCore.Http.TypedResults.Empty.get -> Microsoft.AspNetCore.Http.HttpResults.EmptyHttpResult!
Expand Down
15 changes: 11 additions & 4 deletions src/Http/Http.Results/src/Results.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,13 +678,20 @@ public static IResult ValidationProblem(
return TypedResults.Problem(problemDetails);
}

/// <summary>
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
/// </summary>
/// <returns>The created <see cref="IResult"/> for the response.</returns>
public static IResult Created()
=> TypedResults.Created();

/// <summary>
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
/// </summary>
/// <param name="uri">The URI at which the content has been created.</param>
/// <param name="value">The value to be included in the HTTP response body.</param>
/// <returns>The created <see cref="IResult"/> for the response.</returns>
public static IResult Created(string uri, object? value)
public static IResult Created(string? uri, object? value)
=> Created<object>(uri, value);

/// <summary>
Expand All @@ -693,7 +700,7 @@ public static IResult Created(string uri, object? value)
/// <param name="uri">The URI at which the content has been created.</param>
/// <param name="value">The value to be included in the HTTP response body.</param>
/// <returns>The created <see cref="IResult"/> for the response.</returns>
public static IResult Created<TValue>(string uri, TValue? value)
public static IResult Created<TValue>(string? uri, TValue? value)
=> value is null ? TypedResults.Created(uri) : TypedResults.Created(uri, value);

/// <summary>
Expand All @@ -702,7 +709,7 @@ public static IResult Created<TValue>(string uri, TValue? value)
/// <param name="uri">The URI at which the content has been created.</param>
/// <param name="value">The value to be included in the HTTP response body.</param>
/// <returns>The created <see cref="IResult"/> for the response.</returns>
public static IResult Created(Uri uri, object? value)
public static IResult Created(Uri? uri, object? value)
=> Created<object>(uri, value);

/// <summary>
Expand All @@ -711,7 +718,7 @@ public static IResult Created(Uri uri, object? value)
/// <param name="uri">The URI at which the content has been created.</param>
/// <param name="value">The value to be included in the HTTP response body.</param>
/// <returns>The created <see cref="IResult"/> for the response.</returns>
public static IResult Created<TValue>(Uri uri, TValue? value)
public static IResult Created<TValue>(Uri? uri, TValue? value)
=> value is null ? TypedResults.Created(uri) : TypedResults.Created(uri, value);

/// <summary>
Expand Down
31 changes: 13 additions & 18 deletions src/Http/Http.Results/src/TypedResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -790,18 +790,22 @@ public static ValidationProblem ValidationProblem(
return new(problemDetails);
}

/// <summary>
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
/// </summary>
/// <returns>The created <see cref="HttpResults.Created"/> for the response.</returns>
public static Created Created()
{
return new(default(string));
}

/// <summary>
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
/// </summary>
/// <param name="uri">The URI at which the content has been created.</param>
/// <returns>The created <see cref="HttpResults.Created"/> for the response.</returns>
public static Created Created(string uri)
halter73 marked this conversation as resolved.
Show resolved Hide resolved
public static Created Created(string? uri)
{
if (string.IsNullOrEmpty(uri))
{
throw new ArgumentException("Argument cannot be null or empty", nameof(uri));
}

return new(uri);
}

Expand All @@ -812,13 +816,8 @@ public static Created Created(string uri)
/// <param name="uri">The URI at which the content has been created.</param>
/// <param name="value">The value to be included in the HTTP response body.</param>
/// <returns>The created <see cref="HttpResults.Created{TValue}"/> for the response.</returns>
public static Created<TValue> Created<TValue>(string uri, TValue? value)
public static Created<TValue> Created<TValue>(string? uri, TValue? value)
{
if (string.IsNullOrEmpty(uri))
{
throw new ArgumentException("Argument cannot be null or empty", nameof(uri));
}

return new(uri, value);
}

Expand All @@ -827,10 +826,8 @@ public static Created<TValue> Created<TValue>(string uri, TValue? value)
/// </summary>
/// <param name="uri">The URI at which the content has been created.</param>
/// <returns>The created <see cref="HttpResults.Created"/> for the response.</returns>
public static Created Created(Uri uri)
public static Created Created(Uri? uri)
{
ArgumentNullException.ThrowIfNull(uri);

return new(uri);
}

Expand All @@ -841,10 +838,8 @@ public static Created Created(Uri uri)
/// <param name="uri">The URI at which the content has been created.</param>
/// <param name="value">The value to be included in the HTTP response body.</param>
/// <returns>The created <see cref="HttpResults.Created{TValue}"/> for the response.</returns>
public static Created<TValue> Created<TValue>(Uri uri, TValue? value)
public static Created<TValue> Created<TValue>(Uri? uri, TValue? value)
{
ArgumentNullException.ThrowIfNull(uri);

return new(uri, value);
}

Expand Down
71 changes: 59 additions & 12 deletions src/Http/Http.Results/test/ResultsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,16 @@ public void Content_WithContentAndContentTypeAndEncodingAndStatusCode_ResultHasC
Assert.Equal("text/plain; charset=utf-8", result.ContentType);
}

[Fact]
public void Created_WithNoArgs_SetsLocationNull()
{
//Act
var result = Results.Created() as Created;

//Assert
Assert.Null(result.Location);
}

[Fact]
public void Created_WithStringUriAndValue_ResultHasCorrectValues()
{
Expand Down Expand Up @@ -541,39 +551,75 @@ public void Created_WithUri_ResultHasCorrectValues()
}

[Fact]
public void Created_WithNullStringUri_ThrowsArgException()
public void Created_WithNullStringUri_SetsLocationNull()
{
Assert.Throws<ArgumentException>("uri", () => Results.Created(default(string), null));
//Act
var result = Results.Created(default(string), null) as Created;

//Assert
Assert.Null(result.Location);
}

[Fact]
public void Created_WithEmptyStringUri_ThrowsArgException()
public void Created_WithEmptyStringUri_SetsLocationEmpty()
{
Assert.Throws<ArgumentException>("uri", () => Results.Created(string.Empty, null));
//Act
var result = Results.Created(string.Empty, null) as Created;

//Assert
Assert.Empty(result.Location);
}

[Fact]
public void Created_WithNullUri_ThrowsArgNullException()
public void Created_WithNullUri_SetsLocationNull()
{
Assert.Throws<ArgumentNullException>("uri", () => Results.Created(default(Uri), null));
// Act
var result = Results.Created(default(Uri), null) as Created;

//Assert
Assert.Null(result.Location);
}

[Fact]
public void Created_WithNullStringUriAndValue_ThrowsArgException()
public void Created_WithNullStringUriAndValue_SetsLocationNull()
{
Assert.Throws<ArgumentException>("uri", () => Results.Created(default(string), new { }));
//Arrange
object value = new { };

// Act
var result = Results.Created(default(string), value) as Created<object>;

//Assert
Assert.Null(result.Location);
Assert.Equal(value, result.Value);
}

[Fact]
public void Created_WithEmptyStringUriAndValue_ThrowsArgException()
public void Created_WithEmptyStringUriAndValue_SetsLocationEmpty()
{
Assert.Throws<ArgumentException>("uri", () => Results.Created(string.Empty, new { }));
//Arrange
object value = new { };

// Act
var result = Results.Created(string.Empty, value) as Created<object>;

//Assert
Assert.Empty(result.Location);
Assert.Equal(value, result.Value);
}

[Fact]
public void Created_WithNullUriAndValue_ThrowsArgNullException()
public void Created_WithNullUriAndValue_SetsLocationNull()
{
Assert.Throws<ArgumentNullException>("uri", () => Results.Created(default(Uri), new { }));
//Arrange
object value = new { };

// Act
var result = Results.Created(default(Uri), value) as Created<object>;

//Assert
Assert.Null(result.Location);
Assert.Equal(value, result.Value);
}

[Fact]
Expand Down Expand Up @@ -1295,6 +1341,7 @@ private static string GetMemberName(Expression expression)
(() => Results.Content("content", null, null), typeof(ContentHttpResult)),
(() => Results.Content("content", null, null, null), typeof(ContentHttpResult)),
(() => Results.Created("/path", null), typeof(Created)),
(() => Results.Created(), typeof(Created)),
(() => Results.Created("/path", new()), typeof(Created<object>)),
(() => Results.CreatedAtRoute("routeName", null, null), typeof(CreatedAtRoute)),
(() => Results.CreatedAtRoute("routeName", null, new()), typeof(CreatedAtRoute<object>)),
Expand Down
Loading