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

help wanted: debugging exception inside NSwag 14 #4842

Open
vvdb-architecture opened this issue Apr 2, 2024 · 8 comments
Open

help wanted: debugging exception inside NSwag 14 #4842

vvdb-architecture opened this issue Apr 2, 2024 · 8 comments

Comments

@vvdb-architecture
Copy link

Hello,

I am trying to track down a problem when upgrading from NSwag 13 to NSwag 14. The error message I'm getting during the generation of the CSharp client using the post-build event:

  <Target Name="NSwag" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' ">
    <Exec WorkingDirectory="$(ProjectDir)" EnvironmentVariables="ASPNETCORE_ENVIRONMENT=Development;NSwag=true" Command="$(NSwagExe_Net60) run ..\Sdks\controllers.nswag  /variables:Configuration=$(Configuration)" />
  </Target>

is the following:

15>System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
15> ---> System.InvalidOperationException: This operation is only valid on generic types.
15>   at System.RuntimeType.GetGenericTypeDefinition()
15>   at Namotion.Reflection.ContextualType.<get_Fields>b__36_0(FieldInfo field)
15>   at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
15>   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
15>   at Namotion.Reflection.ContextualType.get_Fields()
15>   at NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, NewtonsoftJsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.ReflectionServiceBase`1.NJsonSchema.Generation.IReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, JsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateInheritance(ContextualType type, JsonSchema schema, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](Type type, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate(Type type, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateInheritance(ContextualType type, JsonSchema schema, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](Type type, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate(Type type, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateInheritance(ContextualType type, JsonSchema schema, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](Type type, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate(Type type, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateArray[TSchemaType](TSchemaType schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.AddProperty(JsonSchema parentSchema, ContextualAccessorInfo property, JsonTypeDescription propertyTypeDescription, String propertyName, Attribute requiredAttribute, Boolean hasRequiredAttribute, Boolean isNullable, Object defaultValue, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonReflectionService.LoadPropertyOrField(JsonProperty jsonProperty, ContextualAccessorInfo accessorInfo, Type parentType, JsonSchema parentSchema, NewtonsoftJsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, NewtonsoftJsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.ReflectionServiceBase`1.NJsonSchema.Generation.IReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, JsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateInheritance(ContextualType type, JsonSchema schema, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](Type type, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate(Type type, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateDictionaryValueSchema[TSchema](JsonSchemaResolver schemaResolver, ContextualType valueType)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateDictionary[TSchemaType](TSchemaType schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.AddProperty(JsonSchema parentSchema, ContextualAccessorInfo property, JsonTypeDescription propertyTypeDescription, String propertyName, Attribute requiredAttribute, Boolean hasRequiredAttribute, Boolean isNullable, Object defaultValue, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonReflectionService.LoadPropertyOrField(JsonProperty jsonProperty, ContextualAccessorInfo accessorInfo, Type parentType, JsonSchema parentSchema, NewtonsoftJsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, NewtonsoftJsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.ReflectionServiceBase`1.NJsonSchema.Generation.IReflectionService.GenerateProperties(JsonSchema schema, ContextualType contextualType, JsonSchemaGeneratorSettings settings, JsonSchemaGenerator schemaGenerator, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.Generate[TSchemaType](ContextualType contextualType, JsonSchemaResolver schemaResolver)
15>   at NJsonSchema.Generation.JsonSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NSwag.Generation.OpenApiSchemaGenerator.GenerateWithReferenceAndNullability[TSchemaType](ContextualType contextualType, Boolean isNullable, JsonSchemaResolver schemaResolver, Action`2 transformation)
15>   at NSwag.Generation.AspNetCore.Processors.OperationResponseProcessor.Process(OperationProcessorContext operationProcessorContext)
15>   at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.RunOperationProcessors(OpenApiDocument document, ApiDescription apiDescription, Type controllerType, MethodInfo methodInfo, OpenApiOperationDescription operationDescription, List`1 allOperations, OpenApiDocumentGenerator generator, OpenApiSchemaResolver schemaResolver)
15>   at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.AddOperationDescriptionsToDocument(OpenApiDocument document, Type controllerType, List`1 operations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver)
15>   at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.GenerateApiGroups(OpenApiDocumentGenerator generator, OpenApiDocument document, IGrouping`2[] apiGroups, OpenApiSchemaResolver schemaResolver)
15>   at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.GenerateAsync(ApiDescriptionGroupCollection apiDescriptionGroups)
15>   at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiCommand.GenerateDocumentWithDocumentProviderAsync(IServiceProvider serviceProvider) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 245
15>   at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiCommand.GenerateDocumentAsync(IServiceProvider serviceProvider, String currentWorkingDirectory) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 239
15>   at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiGeneratorCommandEntryPoint.Process(String commandContent, String outputFile, String applicationName) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiGeneratorCommandEntryPoint.cs:line 29
15>   --- End of inner exception stack trace ---
15>   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
15>   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
15>   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
15>   at NSwag.AspNetCore.Launcher.Program.Main(String[] args) in /_/src/NSwag.AspNetCore.Launcher/Program.cs:line 132
15>System.InvalidOperationException: Swagger generation failed with non-zero exit code '1'.
15>   at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 195
15>   at NSwag.Commands.NSwagDocumentBase.GenerateSwaggerDocumentAsync() in /_/src/NSwag.Commands/NSwagDocumentBase.cs:line 270
15>   at NSwag.Commands.NSwagDocument.ExecuteAsync() in /_/src/NSwag.Commands/NSwagDocument.cs:line 67
15>   at NSwag.Commands.Document.ExecuteDocumentCommand.ExecuteDocumentAsync(IConsoleHost host, String filePath) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 76
15>   at NSwag.Commands.Document.ExecuteDocumentCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 33
15>   at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
15>   at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
15>   at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 65

Now, I would love to know what type is causing the GetGenericTypeDefinition() to trip up and throw an exception.
This worked perfectly with NSwag 13.

For this, I first implemented a processor that narrows down the method on the controller:

public class ControllerFilterProcessor : IOperationProcessor
{
    public bool Process(OperationProcessorContext context)
    {
        Console.WriteLine("[NSWAG] CONTROLLER " + context.ControllerType.Name + " " + context.MethodInfo.Name);
        return true;
    }
}

This is added as follows:

        option.OperationProcessors.Insert(0, new ControllerFilterProcessor());

Sadly, a close inspection did not reveal anything that narrowed down the problem. In fact, before the offending controller is reached, a lot of other controllers and methods with generic types are handled without issue.

Next, I defined a schema processor:

class SchemaProc : ISchemaProcessor
{
    public void Process(SchemaProcessorContext context)
    {
        Console.WriteLine("[NSWAG] SCHEMA " + context.ContextualType.ToString());
    }
}

... which I then injected using:

        option.SchemaSettings.SchemaProcessors.Add(new SchemaProc());

This did not tell me more. Just before the exception occurs, it writes:

15>[NSWAG] SCHEMA Guid: NotNullable

I don't see the connection between a Guid and a a generic type. And in the type being handled, a Guid doesn't even occur.

I noticed in the above stack trace that one of the methods is:

15>   at Namotion.Reflection.ContextualType.get_Fields()

... so I changed the SchemaProc implementation as follows:

class SchemaProc : ISchemaProcessor
{
    public void Process(SchemaProcessorContext context)
    {
        Console.WriteLine("[NSWAG] SCHEMA " + context.ContextualType.ToString());
        try
        {
            var fields = context.ContextualType.Fields.ToArray();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error while getting fields: " + ex.Message);
        }
    }
}

The reasoning is that by calling the method that occurs in the stack trace myself, I could trigger the exception and investigate from there.
Sadly, that didn't work: the body of the above catch is never executed.

The only rational explanation is that the exception is thrown before SchemaProc.Process is being called.

This makes me throw my hands up in the air and ask for help on this forum. What else is there to do? The controllers and their return types are very complicated, and systematically removing types "until it works" will take more time than I have.
Is there some kind of trace flag I can set to have more detailed information?

@vvdb-architecture vvdb-architecture changed the title help wanted: debugging exception inside NSwag help wanted: debugging exception inside NSwag 14 Apr 2, 2024
@danchristensen2000
Copy link

danchristensen2000 commented Apr 4, 2024

I have also run into this same error after upgrading from 13.20.0 to 14.0.7, and am stuck. I have no idea where the error is occurring.

@adam-clauss
Copy link

@vvdb-architecture / @danchristensen2000 - I don't know if you are still trying to solve this, but we ran into what appears to be a very similar error that I noted here #4918

We were able to track down the trigger by running our web api in the debugger with it set to stop on all exceptions. Launch a browser to the swagger.json URL. This caused it to stop in the debugger at that location. By looking at what variables we could see in the debugger (particularly in Namotion.Reflection.ContextualType.Fields.get(), the base.Type pointed directly to the Action type in question), we were able to get a clue as to where this was coming from.

As with you, this issue began appearing after updating from nswag v13 to v14.

@vvdb-architecture
Copy link
Author

vvdb-architecture commented Jul 29, 2024

@adam-clauss : indeed. The issue is very similar. I can confirm what happens.

The exception:

15>System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
15> ---> System.InvalidOperationException: This operation is only valid on generic types.
15>   at System.RuntimeType.GetGenericTypeDefinition()
15>   at Namotion.Reflection.ContextualType.<get_Fields>b__36_0(FieldInfo field)
15>   at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
15>   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
15>   at Namotion.Reflection.ContextualType.get_Fields()

...is actually thrown from code in Namotion.Reflection, more specifically the call to GetGenericTypeDefinition in the implementation of the Fields property of the type ContextualType:

    public ContextualFieldInfo[] Fields
    {
        get
        {
            if (_fields == null)
            {
                lock (this)
                {
                    if (_fields == null)
                    {
                        _fields = base.Type.GetRuntimeFields().Select(delegate (FieldInfo field)
                        {
                            if (base.TypeInfo.IsGenericType && !base.TypeInfo.ContainsGenericParameters)
                            {
                                FieldInfo runtimeField = field.DeclaringType.GetGenericTypeDefinition().GetRuntimeField(field.Name);
                                if (runtimeField != null && runtimeField.FieldType.IsGenericParameter)
                                {
                                    ContextualType contextualType = GenericArguments[runtimeField.FieldType.GenericParameterPosition];
                                    int nullableFlagsIndex = contextualType._nullableFlagsIndex;
                                    return new ContextualFieldInfo(field, ref nullableFlagsIndex, contextualType._nullableFlags);
                                }
                            }

                            int nullableFlagsIndex2 = 0;
                            return new ContextualFieldInfo(field, ref nullableFlagsIndex2, null);
                        }).ToArray();
                    }
                }
            }

            return _fields;
        }
    }

The implementation enumerates all the (runtime) fields of the base.Type.
The problem is that even if the base.Type is a generic type, the field.DeclaringType might not be, since it might be defined in a non-generic base class (as was our case).
Therefore, the GetGenericTypeDefinition() will fail with the exception This operation is only valid on generic types..

The ContextualType.Fields method is called inside the GenerateProperties method of the NewtonsoftJsonReflectionService type in NJsonSchema.NewtonsoftJson.

So now, I need some help on how to best correct this error: is it a Naomotion.Reflection problem? A NJsonSchema.NewtonsoftJson problem? Another problem?

Since I have no illusions on the speed of a resolution, I wil try to circumvent the problem but it looks like it won't be easy to do....

After some further digging, it looks like in the master bransh of Namotion, this was just corrected :

    _fields = Type.GetRuntimeFields().Select(field =>
                            {
                                if (field.DeclaringType is { IsGenericType: true })
                                {
                                    var genericType = field.DeclaringType.GetGenericTypeDefinition();
                                    var genericField = genericType.GetRuntimeField(field.Name);
                                    if (genericField != null && genericField.FieldType.IsGenericParameter)
                                    {
                                        var actualType = GenericArguments[genericField.FieldType.GenericParameterPosition];
                                        var actualIndex = actualType._nullableFlagsIndex;
                                        return new ContextualFieldInfo(field, ref actualIndex, actualType._nullableFlags);
                                    }
                                }

                                var index = 0;
                                return new ContextualFieldInfo(field, ref index, null);
                            }).ToArray();

... but I don't know if we can just include the latest version and have it override whatever the existing NSwag/NJsonSchema version uses...

@vvdb-architecture
Copy link
Author

Does anyone know who to contact/who to beg to to release an updated NSwag with the latest changes of Namotion.Reflection to correct this bug and #4918 ?
This is really really blocking and workarounds are impossible.

Thanks.

@lahma
Copy link
Collaborator

lahma commented Jul 31, 2024

Please remember that you can always patch any parts of the toolchain and compile your own version for your internal use.

@vvdb-architecture
Copy link
Author

vvdb-architecture commented Jul 31, 2024

Please remember that you can always patch any parts of the toolchain and compile your own version for your internal use.

That's simple in theory, but difficult in practice. It would mean generate updated NSwag.* nuget packages, push them to our internal artifact store and then find a way to make all our application builds use these new NSwag.* packages while minimizing the impact of the change so that we can revert back to the official version if/when it's finally updated.

So yeah, not impossible but first let me see if begging @RicoSuter works...

@vvdb-architecture
Copy link
Author

For those who are interested, I found a rather silly workaround, but it works.

The only thing that needs to be upgraded is the Namotion.Reflection assembly.
So download the source from https://github.com/RicoSuter/Namotion.Reflection (say, in C:\PRJ), compile the master branch and add the following target in your .csproj file just before your other targets invoking NSwag:

  <Target Name="NSwagWorkaround" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' ">
    <Copy DestinationFolder="$(OutDir)" SourceFiles="C:\PRJ\Namotion.Reflection\src\Namotion.Reflection\bin\Debug\netstandard2.0\Namotion.Reflection.dll" />
  </Target>

The target will overwrite the buggy DLL and make your error go away. I restrict it to the Debug build, but the choice is yours.

This will enable you to resume your life until @RicoSuter or anyone else with superpowers decides to release a new version with the updated Namotion.Reflection assembly.

@vvdb-architecture
Copy link
Author

Does anyone here have the same rights are @RicoSuter and can that person just make an update of NSwag with the recent version of Namotion.Reflection?
That would at least get one problem out of the way.
Thanks.

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

No branches or pull requests

4 participants