Skip to content

Commit daaebbd

Browse files
Add generic method overloads to Microsoft.AspNetCore.Http.Results static class (#42176)
* Adding new methods * Update API proposal * Update HttpResultsHelper.cs * PR Feedback Co-authored-by: Safia Abdalla <[email protected]> * PR feedback Co-authored-by: Safia Abdalla <[email protected]>
1 parent 88cf8f4 commit daaebbd

File tree

5 files changed

+336
-14
lines changed

5 files changed

+336
-14
lines changed

src/Http/Http.Results/src/HttpResultsHelper.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,21 @@ public static Task WriteResultAsJsonAsync<T>(
2828
return Task.CompletedTask;
2929
}
3030

31-
Log.WritingResultAsJson(logger, typeof(T).Name);
31+
var declaredType = typeof(T);
3232

33-
return httpContext.Response.WriteAsJsonAsync(
33+
Log.WritingResultAsJson(logger, declaredType.Name);
34+
35+
if (declaredType.IsValueType)
36+
{
37+
// In this case the polymorphism is not
38+
// relevant and we don't need to box.
39+
return httpContext.Response.WriteAsJsonAsync(
40+
value,
41+
options: jsonSerializerOptions,
42+
contentType: contentType);
43+
}
44+
45+
return httpContext.Response.WriteAsJsonAsync<object?>(
3446
value,
3547
options: jsonSerializerOptions,
3648
contentType: contentType);

src/Http/Http.Results/src/ProblemHttpResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public Task ExecuteAsync(HttpContext httpContext)
5353
httpContext.Response.StatusCode = code;
5454
}
5555

56-
return HttpResultsHelper.WriteResultAsJsonAsync<object?>(
56+
return HttpResultsHelper.WriteResultAsJsonAsync(
5757
httpContext,
5858
logger,
5959
value: ProblemDetails,

src/Http/Http.Results/src/PublicAPI.Unshipped.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,23 @@ Microsoft.AspNetCore.Http.HttpResults.RedirectToRouteHttpResult.RouteName.get ->
146146
Microsoft.AspNetCore.Http.HttpResults.RedirectToRouteHttpResult.RouteValues.get -> Microsoft.AspNetCore.Routing.RouteValueDictionary?
147147
*REMOVED*static Microsoft.AspNetCore.Http.Results.Content(string! content, string? contentType = null, System.Text.Encoding? contentEncoding = null) -> Microsoft.AspNetCore.Http.IResult!
148148
*REMOVED*static Microsoft.AspNetCore.Http.Results.Content(string! content, Microsoft.Net.Http.Headers.MediaTypeHeaderValue! contentType) -> Microsoft.AspNetCore.Http.IResult!
149+
static Microsoft.AspNetCore.Http.Results.Accepted<TValue>(string? uri = null, TValue? value = default(TValue?)) -> Microsoft.AspNetCore.Http.IResult!
150+
static Microsoft.AspNetCore.Http.Results.AcceptedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default(TValue?)) -> Microsoft.AspNetCore.Http.IResult!
151+
static Microsoft.AspNetCore.Http.Results.BadRequest<TValue>(TValue? error) -> Microsoft.AspNetCore.Http.IResult!
152+
static Microsoft.AspNetCore.Http.Results.Conflict<TValue>(TValue? error) -> Microsoft.AspNetCore.Http.IResult!
149153
static Microsoft.AspNetCore.Http.Results.Content(string? content, Microsoft.Net.Http.Headers.MediaTypeHeaderValue! contentType) -> Microsoft.AspNetCore.Http.IResult!
150154
static Microsoft.AspNetCore.Http.Results.Content(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.IResult!
151155
static Microsoft.AspNetCore.Http.Results.Content(string? content, string? contentType, System.Text.Encoding? contentEncoding) -> Microsoft.AspNetCore.Http.IResult!
152156
*REMOVED*static Microsoft.AspNetCore.Http.Results.Text(string! content, string? contentType = null, System.Text.Encoding? contentEncoding = null) -> Microsoft.AspNetCore.Http.IResult!
157+
static Microsoft.AspNetCore.Http.Results.Created<TValue>(System.Uri! uri, TValue? value) -> Microsoft.AspNetCore.Http.IResult!
158+
static Microsoft.AspNetCore.Http.Results.Created<TValue>(string! uri, TValue? value) -> Microsoft.AspNetCore.Http.IResult!
159+
static Microsoft.AspNetCore.Http.Results.CreatedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default(TValue?)) -> Microsoft.AspNetCore.Http.IResult!
160+
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!
161+
static Microsoft.AspNetCore.Http.Results.NotFound<TValue>(TValue? value) -> Microsoft.AspNetCore.Http.IResult!
162+
static Microsoft.AspNetCore.Http.Results.Ok<TValue>(TValue? value) -> Microsoft.AspNetCore.Http.IResult!
153163
static Microsoft.AspNetCore.Http.Results.Text(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.IResult!
154164
static Microsoft.AspNetCore.Http.Results.Text(string? content, string? contentType, System.Text.Encoding? contentEncoding) -> Microsoft.AspNetCore.Http.IResult!
165+
static Microsoft.AspNetCore.Http.Results.UnprocessableEntity<TValue>(TValue? error) -> Microsoft.AspNetCore.Http.IResult!
155166
static Microsoft.AspNetCore.Http.TypedResults.Content(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
156167
static Microsoft.AspNetCore.Http.TypedResults.Content(string? content, string? contentType, System.Text.Encoding? contentEncoding) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!
157168
static Microsoft.AspNetCore.Http.TypedResults.Text(string? content, string? contentType = null, System.Text.Encoding? contentEncoding = null, int? statusCode = null) -> Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult!

src/Http/Http.Results/src/Results.cs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,22 @@ public static IResult Content(string? content, MediaTypeHeaderValue contentType)
166166
/// <remarks>Callers should cache an instance of serializer settings to avoid
167167
/// recreating cached data with each call.</remarks>
168168
public static IResult Json(object? data, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null)
169+
=> Json<object>(data, options, contentType, statusCode);
170+
171+
/// <summary>
172+
/// Creates a <see cref="IResult"/> that serializes the specified <paramref name="data"/> object to JSON.
173+
/// </summary>
174+
/// <param name="data">The object to write as JSON.</param>
175+
/// <param name="options">The serializer options to use when serializing the value.</param>
176+
/// <param name="contentType">The content-type to set on the response.</param>
177+
/// <param name="statusCode">The status code to set on the response.</param>
178+
/// <returns>The created <see cref="JsonHttpResult{TValue}"/> that serializes the specified <paramref name="data"/>
179+
/// as JSON format for the response.</returns>
180+
/// <remarks>Callers should cache an instance of serializer settings to avoid
181+
/// recreating cached data with each call.</remarks>
182+
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
183+
public static IResult Json<TValue>(TValue? data, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null)
184+
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
169185
=> TypedResults.Json(data, options, contentType, statusCode);
170186

171187
/// <summary>
@@ -454,7 +470,17 @@ public static IResult StatusCode(int statusCode)
454470
/// </summary>
455471
/// <param name="value">The value to be included in the HTTP response body.</param>
456472
/// <returns>The created <see cref="IResult"/> for the response.</returns>
473+
#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
457474
public static IResult NotFound(object? value = null)
475+
#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
476+
=> NotFound<object>(value);
477+
478+
/// <summary>
479+
/// Produces a <see cref="StatusCodes.Status404NotFound"/> response.
480+
/// </summary>
481+
/// <param name="value">The value to be included in the HTTP response body.</param>
482+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
483+
public static IResult NotFound<TValue>(TValue? value)
458484
=> value is null ? TypedResults.NotFound() : TypedResults.NotFound(value);
459485

460486
/// <summary>
@@ -469,15 +495,35 @@ public static IResult Unauthorized()
469495
/// </summary>
470496
/// <param name="error">An error object to be included in the HTTP response body.</param>
471497
/// <returns>The created <see cref="IResult"/> for the response.</returns>
498+
#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
472499
public static IResult BadRequest(object? error = null)
500+
#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
501+
=> BadRequest<object>(error);
502+
503+
/// <summary>
504+
/// Produces a <see cref="StatusCodes.Status400BadRequest"/> response.
505+
/// </summary>
506+
/// <param name="error">An error object to be included in the HTTP response body.</param>
507+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
508+
public static IResult BadRequest<TValue>(TValue? error)
473509
=> error is null ? TypedResults.BadRequest() : TypedResults.BadRequest(error);
474510

475511
/// <summary>
476512
/// Produces a <see cref="StatusCodes.Status409Conflict"/> response.
477513
/// </summary>
478514
/// <param name="error">An error object to be included in the HTTP response body.</param>
479515
/// <returns>The created <see cref="IResult"/> for the response.</returns>
516+
#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
480517
public static IResult Conflict(object? error = null)
518+
#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
519+
=> Conflict<object>(error);
520+
521+
/// <summary>
522+
/// Produces a <see cref="StatusCodes.Status409Conflict"/> response.
523+
/// </summary>
524+
/// <param name="error">An error object to be included in the HTTP response body.</param>
525+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
526+
public static IResult Conflict<TValue>(TValue? error)
481527
=> error is null ? TypedResults.Conflict() : TypedResults.Conflict(error);
482528

483529
/// <summary>
@@ -492,15 +538,35 @@ public static IResult NoContent()
492538
/// </summary>
493539
/// <param name="value">The value to be included in the HTTP response body.</param>
494540
/// <returns>The created <see cref="IResult"/> for the response.</returns>
541+
#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
495542
public static IResult Ok(object? value = null)
543+
#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
544+
=> Ok<object>(value);
545+
546+
/// <summary>
547+
/// Produces a <see cref="StatusCodes.Status200OK"/> response.
548+
/// </summary>
549+
/// <param name="value">The value to be included in the HTTP response body.</param>
550+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
551+
public static IResult Ok<TValue>(TValue? value)
496552
=> value is null ? TypedResults.Ok() : TypedResults.Ok(value);
497553

498554
/// <summary>
499555
/// Produces a <see cref="StatusCodes.Status422UnprocessableEntity"/> response.
500556
/// </summary>
501557
/// <param name="error">An error object to be included in the HTTP response body.</param>
502558
/// <returns>The created <see cref="IResult"/> for the response.</returns>
559+
#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
503560
public static IResult UnprocessableEntity(object? error = null)
561+
#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
562+
=> UnprocessableEntity<object>(error);
563+
564+
/// <summary>
565+
/// Produces a <see cref="StatusCodes.Status422UnprocessableEntity"/> response.
566+
/// </summary>
567+
/// <param name="error">An error object to be included in the HTTP response body.</param>
568+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
569+
public static IResult UnprocessableEntity<TValue>(TValue? error)
504570
=> error is null ? TypedResults.UnprocessableEntity() : TypedResults.UnprocessableEntity(error);
505571

506572
/// <summary>
@@ -580,6 +646,15 @@ public static IResult ValidationProblem(
580646
/// <param name="value">The value to be included in the HTTP response body.</param>
581647
/// <returns>The created <see cref="IResult"/> for the response.</returns>
582648
public static IResult Created(string uri, object? value)
649+
=> Created<object>(uri, value);
650+
651+
/// <summary>
652+
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
653+
/// </summary>
654+
/// <param name="uri">The URI at which the content has been created.</param>
655+
/// <param name="value">The value to be included in the HTTP response body.</param>
656+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
657+
public static IResult Created<TValue>(string uri, TValue? value)
583658
=> value is null ? TypedResults.Created(uri) : TypedResults.Created(uri, value);
584659

585660
/// <summary>
@@ -589,6 +664,15 @@ public static IResult Created(string uri, object? value)
589664
/// <param name="value">The value to be included in the HTTP response body.</param>
590665
/// <returns>The created <see cref="IResult"/> for the response.</returns>
591666
public static IResult Created(Uri uri, object? value)
667+
=> Created<object>(uri, value);
668+
669+
/// <summary>
670+
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
671+
/// </summary>
672+
/// <param name="uri">The URI at which the content has been created.</param>
673+
/// <param name="value">The value to be included in the HTTP response body.</param>
674+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
675+
public static IResult Created<TValue>(Uri uri, TValue? value)
592676
=> value is null ? TypedResults.Created(uri) : TypedResults.Created(uri, value);
593677

594678
/// <summary>
@@ -599,6 +683,18 @@ public static IResult Created(Uri uri, object? value)
599683
/// <param name="value">The value to be included in the HTTP response body.</param>
600684
/// <returns>The created <see cref="IResult"/> for the response.</returns>
601685
public static IResult CreatedAtRoute(string? routeName = null, object? routeValues = null, object? value = null)
686+
=> CreatedAtRoute<object>(routeName, routeValues, value);
687+
688+
/// <summary>
689+
/// Produces a <see cref="StatusCodes.Status201Created"/> response.
690+
/// </summary>
691+
/// <param name="routeName">The name of the route to use for generating the URL.</param>
692+
/// <param name="routeValues">The route data to use for generating the URL.</param>
693+
/// <param name="value">The value to be included in the HTTP response body.</param>
694+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
695+
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
696+
public static IResult CreatedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default)
697+
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
602698
=> value is null ? TypedResults.CreatedAtRoute(routeName, routeValues) : TypedResults.CreatedAtRoute(value, routeName, routeValues);
603699

604700
/// <summary>
@@ -608,6 +704,17 @@ public static IResult CreatedAtRoute(string? routeName = null, object? routeValu
608704
/// <param name="value">The optional content value to format in the response body.</param>
609705
/// <returns>The created <see cref="IResult"/> for the response.</returns>
610706
public static IResult Accepted(string? uri = null, object? value = null)
707+
=> Accepted<object>(uri, value);
708+
709+
/// <summary>
710+
/// Produces a <see cref="StatusCodes.Status202Accepted"/> response.
711+
/// </summary>
712+
/// <param name="uri">The URI with the location at which the status of requested content can be monitored.</param>
713+
/// <param name="value">The optional content value to format in the response body.</param>
714+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
715+
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
716+
public static IResult Accepted<TValue>(string? uri = null, TValue? value = default)
717+
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
611718
=> value is null ? TypedResults.Accepted(uri) : TypedResults.Accepted(uri, value);
612719

613720
/// <summary>
@@ -617,7 +724,21 @@ public static IResult Accepted(string? uri = null, object? value = null)
617724
/// <param name="routeValues">The route data to use for generating the URL.</param>
618725
/// <param name="value">The optional content value to format in the response body.</param>
619726
/// <returns>The created <see cref="IResult"/> for the response.</returns>
727+
#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
620728
public static IResult AcceptedAtRoute(string? routeName = null, object? routeValues = null, object? value = null)
729+
#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads.
730+
=> AcceptedAtRoute<object>(routeName, routeValues, value);
731+
732+
/// <summary>
733+
/// Produces a <see cref="StatusCodes.Status202Accepted"/> response.
734+
/// </summary>
735+
/// <param name="routeName">The name of the route to use for generating the URL.</param>
736+
/// <param name="routeValues">The route data to use for generating the URL.</param>
737+
/// <param name="value">The optional content value to format in the response body.</param>
738+
/// <returns>The created <see cref="IResult"/> for the response.</returns>
739+
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
740+
public static IResult AcceptedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default)
741+
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
621742
=> value is null ? TypedResults.AcceptedAtRoute(routeName, routeValues) : TypedResults.AcceptedAtRoute(value, routeName, routeValues);
622743

623744
/// <summary>

0 commit comments

Comments
 (0)