Skip to content

Add new ModelMetadata constructor for EndpointMetadataApiDescriptionProvider #56867

Closed
@captainsafia

Description

Background and Motivation

Background on this issue can be found in this comment.

Proposed API

// Assembly: Microsoft.AspNetCore.Mvc.Abstractions;
namespace Microsoft.AspNetCore.Mvc.ModelBinding;

public abstract class ModelMetadata : IEquatable<ModelMetadata?>, IModelMetadataProvider
{
+	protected ModelMetadata(Type type, IParameterBindingMetadata? parameterBindingMetadata)
}

Usage Examples

This API is primarily intended for consumption within the EndpointMetadataApiDescriptionProvider to construct the ModelMetadta implementation that is a required part of ApiExplorer metadata.

namespace Microsoft.AspNetCore.Mvc.ApiExplorer;
/// <summary>
/// A metadata description of an input to an API.
/// </summary>
public class ApiParameterDescription
{
/// <summary>
/// Gets or sets the <see cref="ModelMetadata"/>.
/// </summary>
public ModelMetadata ModelMetadata { get; set; } = default!;

For the minimal API-based implementaton of ApiDescriptionProvider, there is a custom EndpointModelMetadtata class that extends the abstract ModelMetadata class that we are modifying:

internal sealed class EndpointModelMetadata : ModelMetadata
{
public EndpointModelMetadata(Type type, IParameterBindingMetadata? parameterBindingMetadata) : base(type, parameterBindingMetadata)
{
IsBindingAllowed = true;
}

For a complete example of how these APIs are used, see aa3ac70.

Alternative Designs

  • Implement ApiExplorer abstraction layer with no MVC dependencies 😛
  • Cry 😭
  • Shift ModelMetadatas use of ParameterBindingCache to the concrete DefaultModelMetadata implementation

Risks

The current shape of this change introduces a regression for scenarios where we generate ModelMetadata for responses or request bodies annotated with Accepts. Unlike parameters, where we can take advantage of the IParameterBindingMetadata that we introduced earlier, there is no similar abstraction layer for response types/accepts metadata. This means that EndpointModelMetadata generated for these will not have information about whether a type is parseable or complex.

We could solve this in one of two ways:

  • Introduce metadata similar to IParameterBindingMetadata for responses and accepts metada and introduce new constructs on ModelMetadata that consume this metadata
  • Call it what it is and document this is a breaking change in the API

I lean slightly towards the later option here -- it's cheaper and we can always revisit and approach #2 if we discover that there were libraries that were taking advantage of ModelMetadata for responses in the minimal API-based API explorer.

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesfeature-openapi

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions