-
Notifications
You must be signed in to change notification settings - Fork 707
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
Using URL segment versioning breaks Swagger generation #1096
Comments
The main issue here is that you haven't updated all of the templates. There are a few actions, specifically I did notice something else that was unexpected and I think is a bug. The version neutral endpoint also needs to have it's route template updated or it will not be an OData action either. However, updating the template does not substitute the API version in the route template as expected. I'm not why that is happening, but it's supposed to work. If you don't have any version-neutral endpoints, then that is a non-issue for you. If you do, then you'll have to provide your own fix in the Swashbuckle extensions until such time as there is a fix for it. |
Thank you for your answer. I always end up getting: If you have any clue, it will be much appreciated. |
I believe you can use attribute routing, but it still has to match the OData conventions or they don't line up. You can verify that by visiting the The only way you can get this error is that there are two different definitions for You also shouldn't use the |
Is there an existing issue for this?
Describe the bug
I'm trying to use the url segment versioning in my project.
I changed the ODataOpenApiExample by adding
options.ApiVersionReader = new UrlSegmentApiVersionReader();
and changing the route Component for
.AddOData(options => options.AddRouteComponents("api/v{version:apiVersion}"))
Seems Ok for V1 but got this exception when trying to see the OpenAPI for V2:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - ApiVersioning.Examples.V2.PeopleController.NewHires (ODataOpenApiExample). See inner exception ---> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate schema for type - Asp.Versioning.OData.ODataValue
1[System.Collections.Generic.IEnumerable1[ApiVersioning.Examples.Models.Person]]. See inner exception ---> System.InvalidOperationException: Can't use schemaId "$PersonIEnumerableODataValue" for type "$Asp.Versioning.OData.ODataValue
1[System.Collections.Generic.IEnumerable1[ApiVersioning.Examples.Models.Person]]". The same schemaId is already used for type "$Asp.Versioning.OData.ODataValue
1[System.Collections.Generic.IEnumerable1[ApiVersioning.Examples.Models.Person]]" at Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.RegisterType(Type type, String schemaId) at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateReferencedSchema(DataContract dataContract, SchemaRepository schemaRepository, Func
1 definitionFactory)at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)
at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
--- End of inner exception stack trace ---
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreateResponseMediaType(ModelMetadata modelMetadata, SchemaRepository schemaRespository)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable
1 source, Func
2 keySelector, Func2 elementSelector, IEqualityComparer
1 comparer)at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponse(ApiDescription apiDescription, SchemaRepository schemaRepository, String statusCode, ApiResponseType apiResponseType)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponses(ApiDescription apiDescription, SchemaRepository schemaRepository)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
--- End of inner exception stack trace ---
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable
1 apiDescriptions, SchemaRepository schemaRepository) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable
1 apiDescriptions, SchemaRepository schemaRepository)at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerDocumentWithoutFilters(String documentName, String host, String basePath)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerAsync(String documentName, String host, String basePath)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)`
The endpoints are working fine.
Expected Behavior
I'd like to have access to the V2 and V3 of OpenAPI.
Steps To Reproduce
This is the modified code of Program.cs in ODataOpenApiExample.
`using ApiVersioning.Examples;
using Asp.Versioning;
using Asp.Versioning.Conventions;
using Microsoft.AspNetCore.OData;
using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.SwaggerGen;
using static Microsoft.AspNetCore.OData.Query.AllowedQueryOptions;
using PeopleControllerV2 = ApiVersioning.Examples.V2.PeopleController;
using PeopleControllerV3 = ApiVersioning.Examples.V3.PeopleController;
var builder = WebApplication.CreateBuilder( args );
// Add services to the container.
builder.Services.AddControllers()
.AddOData(
options =>
{
options.Count().Select().OrderBy();
options.RouteOptions.EnableKeyInParenthesis = false;
options.RouteOptions.EnableNonParenthesisForEmptyParameterFunction = true;
options.RouteOptions.EnablePropertyNameCaseInsensitive = true;
options.RouteOptions.EnableQualifiedOperationCall = false;
options.RouteOptions.EnableUnqualifiedOperationCall = true;
} );
builder.Services.AddProblemDetails();
builder.Services.AddApiVersioning(
options =>
{
// reporting api versions will return the headers
// "api-supported-versions" and "api-deprecated-versions"
options.ReportApiVersions = true;
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddTransient<IConfigureOptions, ConfigureSwaggerOptions>();
builder.Services.AddSwaggerGen(
options =>
{
// add a custom operation filter which sets default values
options.OperationFilter();
var app = builder.Build();
// Configure the HTTP request pipeline.
if ( app.Environment.IsDevelopment() )
{
// navigate to ~/$odata to determine whether any endpoints did not match an odata route template
app.UseODataRouteDebug();
}
app.UseSwagger();
app.UseSwaggerUI(
options =>
{
var descriptions = app.DescribeApiVersions();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
`
Exceptions (if any)
No response
.NET Version
8.0.204
Anything else?
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - ApiVersioning.Examples.V2.PeopleController.NewHires (ODataOpenApiExample). See inner exception
---> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate schema for type - Asp.Versioning.OData.ODataValue
1[System.Collections.Generic.IEnumerable
1[ApiVersioning.Examples.Models.Person]]. See inner exception---> System.InvalidOperationException: Can't use schemaId "$PersonIEnumerableODataValue" for type "$Asp.Versioning.OData.ODataValue
1[System.Collections.Generic.IEnumerable
1[ApiVersioning.Examples.Models.Person]]". The same schemaId is already used for type "$Asp.Versioning.OData.ODataValue1[System.Collections.Generic.IEnumerable
1[ApiVersioning.Examples.Models.Person]]"at Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.RegisterType(Type type, String schemaId)
at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateReferencedSchema(DataContract dataContract, SchemaRepository schemaRepository, Func
1 definitionFactory) at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository) at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo) --- End of inner exception stack trace --- at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreateResponseMediaType(ModelMetadata modelMetadata, SchemaRepository schemaRespository) at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable
1 source, Func2 keySelector, Func
2 elementSelector, IEqualityComparer1 comparer) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponse(ApiDescription apiDescription, SchemaRepository schemaRepository, String statusCode, ApiResponseType apiResponseType) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponses(ApiDescription apiDescription, SchemaRepository schemaRepository) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository) --- End of inner exception stack trace --- at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable
1 apiDescriptions, SchemaRepository schemaRepository)at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerDocumentWithoutFilters(String documentName, String host, String basePath)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerAsync(String documentName, String host, String basePath)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
The text was updated successfully, but these errors were encountered: