Skip to content
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

[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 Nov 5, 2024

The fix seems simple and effective. Any change to get this merged?

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

Successfully merging a pull request may close this issue.

4 participants
@AndreaCuneo @commonsensesoftware @spaasis and others