-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
EndpointMetadataApiDescriptionProvider misses creating ApiDescriptionParameter instances that are defined as BindingSource.Custom or BindingSource.Special. As seen here, EndpointMetadataApiDescriptionProvider only considers parameter candidates via the ParameterInfo acquired through Reflection.
Some BindingSource.Special parameters should be ignored, such as CancellationToken. API Versioning defines the ApiVersion as BindingSource.Special because the value can typically come from one or more places (even zero is technically possible). The value of ApiVersion is set and retrieved through IApiVersioningFeature.
This behavior is a deviation from DefaultApiDescriptionProvider, which considers and creates an ApiParameterDescription for route parameters, even if they don't have a formal ParameterInfo partner (as seen here).
Declaring the formal parameter ApiVersion version will not work because TryParse is delegated to IApiVersionParser so that a developer can opt to change the behavior if they want to. Parsing the value at this point in the pipeline is also too late and affects routing or would result in parsing the value more than once.
Ultimately, EndpointMetadataApiDescriptionProvider should create an ApiParameterDescription for every route parameter in the RoutePattern (e.g. template); regardless of whether there is a corresponding method parameter.
It should be noted that this behavior does not affect routing and it only happens when a developer elects to version solely by URL segment.
Expected Behavior
EndpointMetadataApiDescriptionProvider should have parity with DefaultApiDescriptionProvider wherever possible (obviously modeling binding isn't available for Minimal APIs).
Consider the following:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApiVersioning(options => options.ApiVersionReader = new UrlSegmentApiVersionReader())
.AddApiExplorer(options => options.options.SubstituteApiVersionInUrl = true);
app.MapGet( "v{version:apiVersion}/weatherforecast/{city}", () =>
{
return Enumerable.Range( 1, 5 ).Select( index =>
new WeatherForecast
(
DateTime.Now.AddDays( index ),
Random.Shared.Next( -20, 55 ),
summaries[Random.Shared.Next( summaries.Length )]
) );
} )
.WithApiVersionSet(app.NewApiVersionSet().HasApiVersion(1.0).Build());This should produce ApiDescription.RelativePath with v1/weatherforecast/{city}, but instead produces v{version}/weatherforecast/{city}. Worse still, there is no ApiParameterDescription for {version}. API Versioning relies on the existence of the parameter description and substitutes the token in the template with the corresponding API version value.
This behavior can be reproduced without API Versioning from a pure API Explorer perspective, but the API will not be reachable since the route parameter wouldn't be matched.
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
6.0.300
Anything else?
This was first reported in dotnet/aspnet-api-versioning#830.
ASP.NET Core 6.0
.NET SDK (reflecting any global.json):
Version: 6.0.300
Commit: 8473146e7d
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.300\
Host (useful for support):
Version: 6.0.5
Commit: 70ae3df4a6
.NET SDKs installed:
6.0.202 [C:\Program Files\dotnet\sdk]
6.0.203 [C:\Program Files\dotnet\sdk]
6.0.300 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 3.1.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Metadata
Metadata
Assignees
Labels
Type
Projects
Status