Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[Bug] Properties generated by DefaultModelTypeBuilder have invalid setter: without parameter #1104

Open
1 task done
AndreaCuneo opened this issue Aug 28, 2024 · 1 comment · May be fixed by #1105
Open
1 task done
Assignees

Comments

@AndreaCuneo
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

See domaindrivendev/Swashbuckle.AspNetCore#3051 for details.

Calling NullabilityInfoContext.Create(PropertyInfo) on Properties obtained from the Type generated by DefaultModelTypeBuilder throws IndexOutOfBoundException.

https://github.com/dotnet/runtime/blob/c1a9f26efa4fcf2e3fdcd8557da19d358f51eb00/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs#L217-L222

The culprit is that the generated setter doesn't have a parameter. That's indeed the case in DefaultModelTypeBuilder.

var setter = addTo.DefineMethod( "set_" + name, propertyMethodAttributes, shouldBeAdded, Type.EmptyTypes );

The line should define e null return and a parameter. See documentation.

var setter = addTo.DefineMethod( "set_" + name, propertyMethodAttributes, null, new [] {shouldBeAdded} );

Expected Behavior

NullabilityInfoContext.Create() doesn't throw when called with a Property taken from the generated type from DefaultTypeModelBuilder.

Forwarding Nullability CustomDataAttributes from the original type to the generated type would be nice but not required.

Steps To Reproduce

I don't have a minimal repro. However the non-minimal repro demonstrates the issue.

Clone and checkout ARKlab/Ark.Tools@8c74768
cd Ark.Tools\Samples\TestProject
dotnet test
A test will fail due to an HTTP 500 error, which is caused by the IndexOutOfRangeException inside the test server.

Exceptions (if any)

Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - WebApplicationDemo.Controllers.V1.PeopleController.Get (WebApplicationDemo). See inner exception
 ---> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate schema for type - System.Linq.IQueryable`1[WebApplicationDemo.Dto.Person]. See inner exception
 ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at NullabilityInfo System.Reflection.NullabilityInfoContext.Create(PropertyInfo propertyInfo)
   at NullabilityInfo Swashbuckle.AspNetCore.SwaggerGen.MemberInfoExtensions.GetNullabilityInfo(MemberInfo memberInfo)
   at bool Swashbuckle.AspNetCore.SwaggerGen.MemberInfoExtensions.IsNonNullableReferenceType(MemberInfo memberInfo)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForMember(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, DataProperty dataProperty)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.CreateObjectSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)+() => { } [3]
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateReferencedSchema(DataContract dataContract, SchemaRepository schemaRepository, Func<OpenApiSchema> definitionFactory)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForType(Type modelType, SchemaRepository schemaRepository)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.CreateArraySchema(DataContract dataContract, SchemaRepository schemaRepository)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)+() => { } [1]
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForType(Type modelType, SchemaRepository schemaRepository)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
   --- End of inner exception stack trace ---
   at OpenApiSchema Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)
   at OpenApiMediaType Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreateResponseMediaType(Type modelType, SchemaRepository schemaRespository)
   at OpenApiResponse Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponse(ApiDescription apiDescription, SchemaRepository schemaRepository, string statusCode, ApiResponseType apiResponseType)+(string contentType) => { } [2]
   at Dictionary<TKey, TElement> System.Linq.Enumerable.ToDictionary<TSource, TKey, TElement>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) x 2
   at OpenApiResponse Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponse(ApiDescription apiDescription, SchemaRepository schemaRepository, string statusCode, ApiResponseType apiResponseType)
   at OpenApiResponses Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponses(ApiDescription apiDescription, SchemaRepository schemaRepository)
   at async Task<OpenApiOperation> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperationAsync(ApiDescription apiDescription, SchemaRepository schemaRepository, Func<ApiDescription, SchemaRepository, Task<List<OpenApiParameter>>> parametersGenerator, Func<ApiDescription, SchemaRepository, Task<OpenApiRequestBody>> bodyGenerator, Func<OpenApiOperation, OperationFilterContext, Task> applyFilters)
   --- End of inner exception stack trace ---
   at async Task<OpenApiOperation> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperationAsync(ApiDescription apiDescription, SchemaRepository schemaRepository, Func<ApiDescription, SchemaRepository, Task<List<OpenApiParameter>>> parametersGenerator, Func<ApiDescription, SchemaRepository, Task<OpenApiRequestBody>> bodyGenerator, Func<OpenApiOperation, OperationFilterContext, Task> applyFilters) x 2
   at async Task<Dictionary<OperationType, OpenApiOperation>> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperationsAsync(IEnumerable<ApiDescription> apiDescriptions, SchemaRepository schemaRepository)
   at async Task<OpenApiPaths> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePathsAsync(IEnumerable<ApiDescription> apiDescriptions, SchemaRepository schemaRepository, Func<IGrouping<string, ApiDescription>, SchemaRepository, Task<Dictionary<OperationType, OpenApiOperation>>> operationsGenerator) x 2
   at async Task<OpenApiDocument> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerAsync(string documentName, string host, string basePath)
   at async Task Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at async Task Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
   at async Task Hellang.Middleware.ProblemDetails.ProblemDetailsMiddleware.Invoke(HttpContext context)

.NET Version

net8.0

Anything else?

No response

AndreaCuneo added a commit to ARKlab/aspnet-api-versioning that referenced this issue Aug 28, 2024
The PropertySetter of the SubstitutedType have 0 parameters: they had the same signature of the Getter.

resolves: dotnet#1104
AndreaCuneo added a commit to ARKlab/aspnet-api-versioning that referenced this issue Aug 28, 2024
The PropertySetter of the SubstitutedType have 0 parameters: they had the same signature of the Getter.

resolves: dotnet#1104
@spaasis
Copy link

spaasis commented Feb 4, 2025

This is still quite problematic, since we cannot upgrade many of our references due to this conflict between Versioning + OData + Swashbuckle

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants
@AndreaCuneo @commonsensesoftware @spaasis and others