question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

API Review: Make IAcceptsMetadata and IProducesResponseTypeMetadata public.

See original GitHub issue

Background and Motivation

During the development of the Request Delegate Generator we inject an implementation of the Microsoft.AspNetCore.Http.Metadata.IAcceptsMetadata and Microsoft.AspNetCore.HttpMetadata.IProducesResponseTypeMetadata interfaces.

For non-generated scenarios there is a single implementation of these interfaces that we share via source between all the libraries that require them (src/Shared/RoutingMetadata/AcceptsMetadata.cs and src/Shared/ApiExplorerTypes/ProducesResponseTypeMetadata.cs respectively).

The proposal is that we centralize these types in the Microsoft.AspNetCore.Http.Abstractions assembly. We would use the existing shared soruce internal implementation.

Proposed API

namespace Microsoft.AspNetCore.Http.Metadata

+ public sealed class ProducesResponseTypeMetadata : IProducesResponseTypeMetadata
{
+    public ProducesResponseTypeMetadata(int statusCode)
+    public ProducesResponseTypeMetadata(Type type, int statusCode)
+    public ProducesResponseTypeMetadata(Type type, int statusCode, string contentType, params string[] additionalContentTypes)
+    public Type? Type { get; set; }
+    public int StatusCode { get; set; }
+    public IEnumerable<string> ContentTypes => _contentTypes;
}

public sealed class AcceptsMetadata : IAcceptsMetadata
{
+    public AcceptsMetadata(string[] contentTypes)
+    public AcceptsMetadata(Type? type, bool isOptional, string[] contentTypes)
+    public IReadOnlyList<string> ContentTypes { get; }
+    public Type? RequestType { get; }
+    public bool IsOptional { get; }
}

We may wish to expose a type with content values used in the constructor of these types (e.g. application/json).

Usage Examples

Usage if this type already exists in the framework today because it is shared source:

https://github.com/dotnet/aspnetcore/blob/e313fbec2f1156e0e9db64e098474590b64ce269/src/Mvc/Mvc.Core/src/Routing/ActionEndpointFactory.cs#L424

https://github.com/dotnet/aspnetcore/blob/e313fbec2f1156e0e9db64e098474590b64ce269/src/Http/Routing/src/Builder/OpenApiRouteHandlerBuilderExtensions.cs#L231

https://github.com/dotnet/aspnetcore/blob/e313fbec2f1156e0e9db64e098474590b64ce269/src/Http/Http.Results/src/CreatedOfT.cs#L102

All of these usages would be updated to use the new public type.

Alternative Designs

Because this came up during the development of the source generator we could try to publish a “support assembly” for types that we need in the source generator. This support assembly would contain public concrete implementations for interfaces like IAcceptsMetadata. The idea would be that these types don’t have the same API compatibility guarantees as the rest of the framework since they are designed to work alongside the matching source generator.

Risks

By not exposing an implementation of IAcceptsMetadata and IProducesResponseTypeMetadata we currently force developers to use the interface if they want to inspect the metadata. We want them to continue during this - however if we make the types public they might start using the concrete types. Although perhaps this is desirable in cases when they want to mutate the metadata on an endpoint themselves.

Unfortunately we can’t use IVT in this scenario because we need to be able to access the types in the generated source.

Issue Analytics

  • State:closed
  • Created 5 months ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
halter73commented, Jun 26, 2023

API Review Notes:

  • We’re trying to remove shared source usage in light of RDG.
  • IAcceptsMetadata is already implemented by MVCs ConsumesAttribute. Do we need another attribute?
    • MVC brings in extra dependencies and implements other interfaces like IResourceFilter which makes something like type forwarding impractical.
  • ProducesAttribute does not implement IProducesResponseTypeMetadata.
    • We think this is because the interface does not support content negotiation which MVC needs.
  • Isn’t this similar to [FromBody], [FromService], [FromRoute], etc…?
    • So far we’ve just told people to take the MVC dependency to avoid duplication and confusion.
  • What assembly would this live in?
    • Probably Http.Abstractions along with the interfaces.
    • It cannot go into Microsoft.AspNetCore.Metadata because it does not depend on Http.Abstractions.
  • These are not attributes. Should they be?
    • It would be sad to add attributes for the same thing later, but we don’t want to create confusion with MVC.
  • Do these need to “work” with MVC?
    • Would this just mean API explorer honors it?
  • Do we need so many constructors for something that’s mostly for internal use?
  • Does ProducesResponseTypeMetadata need setters?
    • No
  • Do we like default values for optional constructor parameters?
    • Yes.
  • What about the namespace?
    • Let’s keep it as Microsoft.AspNetCore.Http.Metadata to match the interfaces.
  • Are we happy with sealed?
    • Yes.

API Approved!

// Microsoft.AspNetCore.Http.Abstractions.dll
namespace Microsoft.AspNetCore.Http.Metadata;

+ public sealed class ProducesResponseTypeMetadata : IProducesResponseTypeMetadata
+ {
+    public ProducesResponseTypeMetadata(int statusCode, Type? type = null,  string[]? contentTypes = null)
+    public Type? Type { get; }
+    public int StatusCode { get; }
+    public IEnumerable<string> ContentTypes { get; }
+ }

+ public sealed class AcceptsMetadata : IAcceptsMetadata
+ {
+    public AcceptsMetadata(string[] contentTypes, Type? requestType = null, bool isOptional = false)
+    public IReadOnlyList<string> ContentTypes { get; }
+    public Type? RequestType { get; }
+    public bool IsOptional { get; }
+ }
0reactions
mitchdennycommented, Jul 3, 2023

PR is up for this. Ended up touching a fair amount of surface area.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Design: IEndpointConventionBuilder Extensions Unusable ...
And as mentioned in the API Review Notes, WithMetadata can be used manually with attributes if needed. But as you note above, there...
Read more >
Work with review data - Business Profile APIs
The Google My Business API provides you with the ability to work with review data to perform the following operations: List all reviews....
Read more >
AIP-100: API Design Review FAQ
API design review exists to ensure a simple, intuitive, and consistent API experience throughout our API corpus. Do I need API design approval?...
Read more >
Google Play In-App Reviews API
The Google Play In-App Review API lets you prompt users to submit Play Store ratings and reviews without the inconvenience of leaving your ......
Read more >
Trustpilot API Documentation
Welcome to the documentation for Trustpilot Public and Customer APIs. ... The business unit hosts a company's rating, its reviews, and the company...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found