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