-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
Introduce interfaces to describe IResult types #42187
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:
|
API review notes:
API needs update, @brunolins16 will update with the full diff once testing a couple things. |
The covariance/contravariance works for reference types only (SharpLab sample): With that, I think this is not true if using
I feel that it might be confusing and probably keeping the |
Here, is the updated proposal, keeping the ### Interfaces
namespace Microsoft.AspNetCore.Http
{
+ public interface IStatusCodeHttpResult
+ {
+ int StatusCode { get; }
+ }
+ public interface IValueHttpResult
+ {
+ object? RawValue { get; }
+ }
+ public interface IValueHttpResult<out TValue>
+ {
+ TValue? Value { get; }
+ }
+ public interface IContentTypeHttpResult
+ {
+ string? ContentType { get; }
+ }
+ public interface IFileHttpResult
+ {
+ string? ContentType { get; }
+ string? FileDownloadName { get; }
+ }
+ public interface INestedHttpResult
+ {
+ IResult Result { get; }
+ }
}
### Result Types
namespace Microsoft.AspNetCore.Http.HttpResults;
{
- public sealed class Accepted : IResult, IEndpointMetadataProvider
+ public sealed class Accepted : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class AcceptedAtRoute : IResult, IEndpointMetadataProvider
+ public sealed class AcceptedAtRoute : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class AcceptedAtRoute<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class AcceptedAtRoute<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Accepted<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Accepted<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class BadRequest : IResult, IEndpointMetadataProvider
+ public sealed class BadRequest : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class BadRequest<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class BadRequest<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Conflict : IResult, IEndpointMetadataProvider
+ public sealed class Conflict : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class Conflict<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Conflict<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class ContentHttpResult : IResult
+ public sealed partial class ContentHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult
- public sealed class Created : IResult, IEndpointMetadataProvider
+ public sealed class Created : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class CreatedAtRoute : IResult, IEndpointMetadataProvider
+ public sealed class CreatedAtRoute : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class CreatedAtRoute<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class CreatedAtRoute<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Created<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Created<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class FileContentHttpResult : IResult
+ public sealed partial class FileContentHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class FileStreamHttpResult : IResult
+ public sealed class FileStreamHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed partial class JsonHttpResult<TValue> : IResult
+ public sealed partial class JsonHttpResult<TValue> : IResult, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>, IContentTypeHttpResult
- public class NoContent : IResult, IEndpointMetadataProvider
+ public class NoContent : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class NotFound : IResult, IEndpointMetadataProvider
+ public sealed class NotFound : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class NotFound<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class NotFound<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Ok : IResult, IEndpointMetadataProvider
+ public sealed class Ok : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class Ok<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Ok<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class PhysicalFileHttpResult : IResult
+ public sealed partial class PhysicalFileHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class ProblemHttpResult : IResult
+ public sealed class ProblemHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult<ProblemDetails>
{
- public int? StatusCode { get; }
+ public int StatusCode { get; }
}
- public sealed class PushStreamHttpResult : IResult
+ public sealed class PushStreamHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class Results<TResult1, TResultN> : IResult, IEndpointMetadataProvider
+ public sealed class Results<TResult1, TResultN> : IResult, INestedHttpResult, IEndpointMetadataProvider
- public sealed partial class StatusCodeHttpResult : IResult
+ public sealed partial class StatusCodeHttpResult : IResult, IStatusCodeHttpResult
- public sealed class UnauthorizedHttpResult : IResult
+ public sealed class UnauthorizedHttpResult : IResult, IStatusCodeHttpResult
- public sealed class UnprocessableEntity : IResult, IEndpointMetadataProvider
+ public sealed class UnprocessableEntity : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class UnprocessableEntity<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class UnprocessableEntity<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class ValidationProblem : IResult, IEndpointMetadataProvider
+ public sealed class ValidationProblem : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult<HttpValidationProblemDetails>
- public sealed class VirtualFileHttpResult : IResult
+ public sealed class VirtualFileHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
} |
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 interface IStatusCodeHttpResult
+ {
+ int StatusCode { get; }
+ }
+ public interface IValueHttpResult
+ {
+ object? RawValue { get; }
+ }
+ public interface IValueHttpResult<out TValue>
+ {
+ TValue? Value { get; }
+ }
+ public interface IContentTypeHttpResult
+ {
+ string? ContentType { get; }
+ }
+ public interface IFileHttpResult
+ {
+ string? ContentType { get; }
+ string? FileDownloadName { get; }
+ }
+ public interface INestedHttpResult
+ {
+ IResult Result { get; }
+ }
}
### Result Types
namespace Microsoft.AspNetCore.Http.HttpResults;
{
- public sealed class Accepted : IResult, IEndpointMetadataProvider
+ public sealed class Accepted : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class AcceptedAtRoute : IResult, IEndpointMetadataProvider
+ public sealed class AcceptedAtRoute : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class AcceptedAtRoute<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class AcceptedAtRoute<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Accepted<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Accepted<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class BadRequest : IResult, IEndpointMetadataProvider
+ public sealed class BadRequest : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class BadRequest<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class BadRequest<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Conflict : IResult, IEndpointMetadataProvider
+ public sealed class Conflict : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class Conflict<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Conflict<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class ContentHttpResult : IResult
+ public sealed partial class ContentHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult
- public sealed class Created : IResult, IEndpointMetadataProvider
+ public sealed class Created : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class CreatedAtRoute : IResult, IEndpointMetadataProvider
+ public sealed class CreatedAtRoute : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class CreatedAtRoute<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class CreatedAtRoute<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Created<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Created<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class FileContentHttpResult : IResult
+ public sealed partial class FileContentHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class FileStreamHttpResult : IResult
+ public sealed class FileStreamHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed partial class JsonHttpResult<TValue> : IResult
+ public sealed partial class JsonHttpResult<TValue> : IResult, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>, IContentTypeHttpResult
- public class NoContent : IResult, IEndpointMetadataProvider
+ public class NoContent : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class NotFound : IResult, IEndpointMetadataProvider
+ public sealed class NotFound : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class NotFound<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class NotFound<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Ok : IResult, IEndpointMetadataProvider
+ public sealed class Ok : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class Ok<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Ok<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class PhysicalFileHttpResult : IResult
+ public sealed partial class PhysicalFileHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class ProblemHttpResult : IResult
+ public sealed class ProblemHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult<ProblemDetails>
{
- public int? StatusCode { get; }
+ public int StatusCode { get; }
}
- public sealed class PushStreamHttpResult : IResult
+ public sealed class PushStreamHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class Results<TResult1, TResultN> : IResult, IEndpointMetadataProvider
+ public sealed class Results<TResult1, TResultN> : IResult, INestedHttpResult, IEndpointMetadataProvider
- public sealed partial class StatusCodeHttpResult : IResult
+ public sealed partial class StatusCodeHttpResult : IResult, IStatusCodeHttpResult
- public sealed class UnauthorizedHttpResult : IResult
+ public sealed class UnauthorizedHttpResult : IResult, IStatusCodeHttpResult
- public sealed class UnprocessableEntity : IResult, IEndpointMetadataProvider
+ public sealed class UnprocessableEntity : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class UnprocessableEntity<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class UnprocessableEntity<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class ValidationProblem : IResult, IEndpointMetadataProvider
+ public sealed class ValidationProblem : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult<HttpValidationProblemDetails>
- public sealed class VirtualFileHttpResult : IResult
+ public sealed class VirtualFileHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
} API Approved! |
@BrennanConroy when I change the hierarchy, I forgot to change the public interface IValueHttpResult
{
- object? RawValue { get; }
+ object? Value { get; }
} |
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 interface IStatusCodeHttpResult
+ {
+ int StatusCode { get; }
+ }
+ public interface IValueHttpResult
+ {
+ object? Value { get; }
+ }
+ public interface IValueHttpResult<out TValue>
+ {
+ TValue? Value { get; }
+ }
+ public interface IContentTypeHttpResult
+ {
+ string? ContentType { get; }
+ }
+ public interface IFileHttpResult
+ {
+ string? ContentType { get; }
+ string? FileDownloadName { get; }
+ }
+ public interface INestedHttpResult
+ {
+ IResult Result { get; }
+ }
}
### Result Types
namespace Microsoft.AspNetCore.Http.HttpResults;
{
- public sealed class Accepted : IResult, IEndpointMetadataProvider
+ public sealed class Accepted : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class AcceptedAtRoute : IResult, IEndpointMetadataProvider
+ public sealed class AcceptedAtRoute : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class AcceptedAtRoute<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class AcceptedAtRoute<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Accepted<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Accepted<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class BadRequest : IResult, IEndpointMetadataProvider
+ public sealed class BadRequest : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class BadRequest<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class BadRequest<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Conflict : IResult, IEndpointMetadataProvider
+ public sealed class Conflict : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class Conflict<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Conflict<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class ContentHttpResult : IResult
+ public sealed partial class ContentHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult
- public sealed class Created : IResult, IEndpointMetadataProvider
+ public sealed class Created : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class CreatedAtRoute : IResult, IEndpointMetadataProvider
+ public sealed class CreatedAtRoute : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class CreatedAtRoute<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class CreatedAtRoute<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Created<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Created<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class FileContentHttpResult : IResult
+ public sealed partial class FileContentHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class FileStreamHttpResult : IResult
+ public sealed class FileStreamHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed partial class JsonHttpResult<TValue> : IResult
+ public sealed partial class JsonHttpResult<TValue> : IResult, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>, IContentTypeHttpResult
- public class NoContent : IResult, IEndpointMetadataProvider
+ public class NoContent : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class NotFound : IResult, IEndpointMetadataProvider
+ public sealed class NotFound : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class NotFound<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class NotFound<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class Ok : IResult, IEndpointMetadataProvider
+ public sealed class Ok : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class Ok<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class Ok<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed partial class PhysicalFileHttpResult : IResult
+ public sealed partial class PhysicalFileHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class ProblemHttpResult : IResult
+ public sealed class ProblemHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult<ProblemDetails>
{
- public int? StatusCode { get; }
+ public int StatusCode { get; }
}
- public sealed class PushStreamHttpResult : IResult
+ public sealed class PushStreamHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
- public sealed class Results<TResult1, TResultN> : IResult, IEndpointMetadataProvider
+ public sealed class Results<TResult1, TResultN> : IResult, INestedHttpResult, IEndpointMetadataProvider
- public sealed partial class StatusCodeHttpResult : IResult
+ public sealed partial class StatusCodeHttpResult : IResult, IStatusCodeHttpResult
- public sealed class UnauthorizedHttpResult : IResult
+ public sealed class UnauthorizedHttpResult : IResult, IStatusCodeHttpResult
- public sealed class UnprocessableEntity : IResult, IEndpointMetadataProvider
+ public sealed class UnprocessableEntity : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult
- public sealed class UnprocessableEntity<TValue> : IResult, IEndpointMetadataProvider
+ public sealed class UnprocessableEntity<TValue> : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult<TValue>
- public sealed class ValidationProblem : IResult, IEndpointMetadataProvider
+ public sealed class ValidationProblem : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult<HttpValidationProblemDetails>
- public sealed class VirtualFileHttpResult : IResult
+ public sealed class VirtualFileHttpResult : IResult, IFileHttpResult, IContentTypeHttpResult
} |
Background and Motivation
The #40656 issue made all
IResult
concrete types publicly available, at that time the main goal was to make the Minimal API endpoints unit tests easier. As part of the original design was decided to remove all the hierarchy and make all typessealed
, however, with the introduction of the ability to addFilters
to an endpoint shows that, based on community feedback, without a more generalized way to describe anIResult
type (as we have inActionResult
types) thefilter
implementation become more complex, since is needed to have atype check
for every possibility.Proposed API
The proposal is to introduce the following interfaces that will describe the public
IResult
types:Also, as part of the proposal the
IResult
types must be updated to implement the new interfaces:Usage Examples
Alternative Designs
A simple hierarchy is proposed in my original design, that helps users to create their code, however, an alternative design is remove the hierarchy (as same as the public available types) and update the
IResult
types to implement all of them explicitly. Eg.:Risks
I don't see a risk in the API proposal since it only introduces a new set of interfaces.
The text was updated successfully, but these errors were encountered: