-
Notifications
You must be signed in to change notification settings - Fork 10k
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
Add generic method overloads to Microsoft.AspNetCore.Http.Results static class #41724
Comments
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
cc @JamesNK for trim friendliness. |
Thanks for contacting us. We're moving this issue to the |
API review notes:
namespace Microsoft.AspNetCore.Http;
public static class Results
{
+ public static IResult Accepted<TValue>(TValue? value);
+ public static IResult AcceptedAtRoute<TValue>(string? routeName, object? routeValues = null, TValue? value = null);
+ public static IResult BadRequest<TValue>(TValue? error);
+ public static IResult Conflict<TValue>(TValue? error);
+ public static IResult Created<TValue>(string uri, TValue? value);
+ public static IResult Created<TValue>(Uri uri, TValue? value);
+ public static IResult CreatedAtRoute<TValue>(string? routeName, object? routeValues = null, TValue? value = null);
+ public static IResult Json<TValue>(TValue value, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null);
+ public static IResult NotFound<TValue>(TValue? value);
+ public static IResult Ok<TValue>(TValue? value);
+ public static IResult UnprocessableEntity<TValue>(TValue? error);
}
Given the nuanced breaking change discussion, we'll continue this next time. |
I just tested this behavior and TypedResults and Results are behaving differently. Eg.: public class BaseModel
{
public int BaseProperty { get; set; }
}
public class ChildModel : BaseModel
{
public int ChildProperty { get; set; }
}
// response: {"baseProperty":1}
app.MapGet("/typed-results", () =>
{
BaseModel model = new ChildModel() { BaseProperty = 1, ChildProperty = 2 };
return TypedResults.Ok(model);
});
// response: {"childProperty":2,"baseProperty":1}
app.MapGet("/results", () =>
{
BaseModel model = new ChildModel() { BaseProperty = 1, ChildProperty = 2 };
return Results.Ok(model);
}); |
@halter73 another one! |
@davidfowl yeah he was the one who brought it up in API review. It's a little concerning to me how unintuitive this feels but being consistent is the most important thing. |
Consistently unintuitive. |
At this point ( not questioning what is correct) , should we update the TypedResults or any generic method to behave as Results? |
This is still my position. We should always serialize all properties to JSON which is what we have been doing when you return the object directly or you've used the untyped |
Yeah I meant more the inconsistency between what |
They pass the type argument directly through to |
Right, that's the kind of inconsistency I'm talking about: the extensions on |
But then, if we want to return the same generic result types from the new generic I don't like having an inconsistency between Here are the options I see:
|
Yep I agree, make |
We should talk about trim ability as well? Calling @JamesNK and @eiriktsarpalis and @eerhardt |
Is anything about serializing the return type of an arbitrary |
I'm wondering if we want more overloads like we did for Json to support the System.Text.Json source generator. |
Yes. Methods like these will never be 100% trim safe: public static IResult Ok<TValue>(TValue? value);
public static IResult Json<TValue>(TValue value, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null) Don't worry about trimming behavior with them. Overloads that take app.MapGet("/typed-results", () =>
{
BaseModel model = new ChildModel() { BaseProperty = 1, ChildProperty = 2 };
// Note the generated context. I don't think this would compile.
// I think the compiler would complain that you're passing it a BaseModel and say that a ChildModel is required.
return TypedResults.Ok(model, MyJsonContext.ChildModel);
}); But, this is only making the response trim safe. Request parameter args types aren't preserved and will only work if placed in an assembly that's excluded from trimming. |
Updating the proposed API to reflect some additional proposed changes: namespace Microsoft.AspNetCore.Http;
public static class Results
{
- public static IResult Accepted<TValue>(TValue? value);
+ public static IResult Accepted<TValue>(string? uri = null, TValue? value = default);
- public static IResult AcceptedAtRoute<TValue>(string? routeName, object? routeValues = null, TValue? value = null);
+ public static IResult AcceptedAtRoute<TValue>((string? routeName = null, object? routeValues = null, TValue? value = default);
+ public static IResult BadRequest<TValue>(TValue? error);
+ public static IResult Conflict<TValue>(TValue? error);
+ public static IResult Created<TValue>(string uri, TValue? value);
+ public static IResult Created<TValue>(Uri uri, TValue? value);
- public static IResult CreatedAtRoute<TValue>(string? routeName, object? routeValues = null, TValue? value = null);
+ public static IResult CreatedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default);
+ public static IResult Json<TValue>(TValue value, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null);
+ public static IResult NotFound<TValue>(TValue? value);
+ public static IResult Ok<TValue>(TValue? value);
+ public static IResult UnprocessableEntity<TValue>(TValue? error);
}
|
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
I don't see overloads taking either of these types. Should we add them? |
I think we should, also add to the |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
API review notes:
namespace Microsoft.AspNetCore.Http;
public static class Results
{
+ public static IResult Accepted<TValue>(string? uri = null, TValue? value = default);
+ public static IResult AcceptedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default);
+ public static IResult BadRequest<TValue>(TValue? error);
+ public static IResult Conflict<TValue>(TValue? error);
+ public static IResult Created<TValue>(string uri, TValue? value);
+ public static IResult Created<TValue>(Uri uri, TValue? value);
+ public static IResult CreatedAtRoute<TValue>(string? routeName = null, object? routeValues = null, TValue? value = default);
+ public static IResult Json<TValue>(TValue value, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null);
+ public static IResult NotFound<TValue>(TValue? value);
+ public static IResult Ok<TValue>(TValue? value);
+ public static IResult UnprocessableEntity<TValue>(TValue? error);
} API approved! |
As a follow-up to making the in-box
IResult
-implementing types public and the introduction of typed results likeOk<TValue>
, we should add new generic overloads to the methods on theMicrosoft.AspNetCore.Http.Results
static factory class that accept a value that is ultimately passed to the equivalent generic method onMicrosoft.AspNetCore.Http.TypedResults
, thus preserving the concrete type of the passed object. With the concrete type preserved, logic inspecting the runtime return types (e.g. unit tests, filters) can use pattern matching techniques to check for the desired type.These new methods should continue to return
IResult
so that all methods on theResults
class are easy to use in inferredIResult
returning lambdas where multiplereturn
statements exist. TheTypedResults
class will remain the way to create instances of in-boxIResult
-implementing types while preserving the concrete type (primarily for use with theResults<TResult1, TResultN>
union type).Note that these new methods will be bound by the compiler for existing source code in projects updated from .NET 6 to .NET 7. We don't treat this as a breaking change however given the declared return type will remain
IResult
and the runtime types in .NET 6 were not public, so any reference to them must have used unsupported approaches anyway (e.g. reflection).Examples
Suggested API
The text was updated successfully, but these errors were encountered: