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

Could not generated C# client from AAS Repository OpenAPI document #285

Open
1 task done
huf1 opened this issue May 6, 2024 · 10 comments
Open
1 task done

Could not generated C# client from AAS Repository OpenAPI document #285

huf1 opened this issue May 6, 2024 · 10 comments
Labels
bug Something isn't working

Comments

@huf1
Copy link

huf1 commented May 6, 2024

What happens?

I'm trying to generate a C# client with NSwag from the provided AAS Repository document, but it fails with an error message.
Steps to reproduce:

  1. https://app.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShellRepositoryServiceSpecification/V3.0.1_SSP-001 -> Download API -> JSON Resolved
  2. Run command: dotnet-nswag.exe openapi2csclient /className:AaSRepositoryClient /namespace:AasRepositoryClient /GenerateExceptionClasses:false /input:"C:\temp\AasRepositorySpec.json" /output:"C:\temp\AasRepositoryClient.cs"

Error message:
System.InvalidOperationException: The properties 'modelType' are defined multiple times.

StackTrace:
System.InvalidOperationException: The properties 'modelType' are defined multiple times. at NJsonSchema.JsonSchema.get_ActualProperties() at NSwag.CodeGeneration.Models.ParameterModelBase..ctor(String parameterName, String variableName, String typeName, OpenApiParameter parameter, IList1 allParameters, CodeGeneratorSettingsBase settings, IClientGenerator generator, TypeResolverBase typeResolver) in //src/NSwag.CodeGeneration/Models/ParameterModelBase.cs:line 52
at NSwag.CodeGeneration.CSharp.Models.CSharpParameterModel..ctor(String parameterName, String variableName, String variableIdentifier, String typeName, OpenApiParameter parameter, IList1 allParameters, CodeGeneratorSettingsBase settings, IClientGenerator generator, TypeResolverBase typeResolver) in /_/src/NSwag.CodeGeneration.CSharp/Models/CSharpParameterModel.cs:line 40 at NSwag.CodeGeneration.CSharp.Models.CSharpOperationModel.<>c__DisplayClass5_0.<.ctor>b__5(OpenApiParameter parameter) in /_/src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs:line 76 at System.Linq.Enumerable.SelectListIterator2.Fill(ReadOnlySpan1 source, Span1 destination, Func2 func) at System.Linq.Enumerable.SelectListIterator2.ToList()
at NSwag.CodeGeneration.CSharp.Models.CSharpOperationModel..ctor(OpenApiOperation operation, CSharpGeneratorBaseSettings settings, CSharpGeneratorBase generator, CSharpTypeResolver resolver) in /
/src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs:line 74
at NSwag.CodeGeneration.CSharp.CSharpClientGenerator.CreateOperationModel(OpenApiOperation operation, ClientGeneratorBaseSettings settings) in //src/NSwag.CodeGeneration.CSharp/CSharpClientGenerator.cs:line 81
at NSwag.CodeGeneration.ClientGeneratorBase3.GetOperations(OpenApiDocument document) in /_/src/NSwag.CodeGeneration/ClientGeneratorBase.cs:line 173 at NSwag.CodeGeneration.ClientGeneratorBase3.GenerateAllClientTypes() in /
/src/NSwag.CodeGeneration/ClientGeneratorBase.cs:line 106
at NSwag.CodeGeneration.ClientGeneratorBase3.GenerateFile(ClientGeneratorOutputType outputType) in /_/src/NSwag.CodeGeneration/ClientGeneratorBase.cs:line 73 at NSwag.Commands.CodeGeneration.OpenApiToCSharpClientCommand.RunAsync() in /_/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs:line 292 at NSwag.Commands.CodeGeneration.OpenApiToCSharpClientCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs:line 270 at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input) at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input) at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 65

Toolchain:
NSwag - NSwag command line tool for .NET Core Net80, toolchain v14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))

Why is this wrong?

Generating C# client should work with an OpenAPI supporting tool like NSwag.

How should it be fixed?

Client generation is essential for developing against this or even other specificated APIs

  • I have signed the required Developer Certificate of Origin (DCO) already.
@huf1 huf1 added the bug Something isn't working label May 6, 2024
@sebbader-sap
Copy link
Contributor

sebbader-sap commented May 15, 2024

The provided files are 100% correct OpenAPI. I don't know NSwag but it looks like a problem on their side. Not all OpenAPI generators are able to deal with the expressiveness of the OpenAPI specification, might be the case here too.

However, you may want to have a look at this C# SDK: https://github.com/aas-core-works/aas-core3.0-csharp

@mrumurm
Copy link

mrumurm commented Jun 13, 2024

We tried different generators(swagger codegen / openapi-generator / swagger hub download ) and it was not possible to generate a client without Errors / Problems.

We also tried to generate for different Languages like C#, GO, JAVA.

Also while trying to download the JAVA Client swaggerhub even didnt create the Package and showed this error:
Bildschirmfoto 2024-06-12 um 10 05 54

This swagger definition was used: Submodel Repository Service

Could you provide a working client generation example for this Swagger definition ?

@arteeh
Copy link

arteeh commented Jun 14, 2024

@mrumurm Maybe try Kiota as the code generator. I haven't tested it much but it seems to work okay with the spec provided by BaSyx.

But I do agree that these openapi specs don't seem to be very generator-friendly.

@arteeh
Copy link

arteeh commented Aug 13, 2024

As of version 2 milestone 3 of BaSyx, I can no longer use Kiota to generate an API from their AAS Environment application. I opened an issue here, and they referred me back to the IDTA specs.

Feeding https://api.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShell-API/V1.0RC03 to NSwag Studio give me this error:

System.InvalidOperationException: Could not find the JSON path of a referenced schema: Manually referenced schemas must be added to the 'Definitions' of a parent schema.

I give up on NSwag again and try Kiota with this command:

kiota generate -l CSharp -o ./Generated -n IDTApi -d https://api.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShell-Environment/V1.0RC03 --exclude-backward-compatible --log-level Information --co

It complains about external references:

External references are not supported in this version of Kiota. While Kiota awaits on OpenAPI.Net to support inlining external references, you can use https://www.nuget.org/packages/Microsoft.OpenApi.Hidi to generate an OpenAPI description with inlined external references and then use this new reference with Kiota.

So I follow the recommendation and use their Hidi tool to combine the specs:

dotnet tool install --global Microsoft.OpenApi.Hidi
hidi transform -d  https://api.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShell-Environment/V1.0RC03 --inline-external

That command spits out errors:

fail: Microsoft.OpenApi.Hidi.Handlers.TransformCommandHandler[0]
      => Parsing OpenAPI: https://api.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShell-Environment/V1.0RC03 => Detected errors
      Detected error during parsing: [File: https://api.swaggerhub.com/domains/Plattform_i40/Part1-MetaModel-Schemas/V3.0RC02] The field 'paths' in 'document' object is REQUIRED. [#/paths]
fail: Microsoft.OpenApi.Hidi.Handlers.TransformCommandHandler[0]
      => Parsing OpenAPI: https://api.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShell-Environment/V1.0RC03 => Detected errors
      Detected error during parsing: [File: https://api.swaggerhub.com/domains/Plattform_i40/Part2-API-Schemas/V1.0RC03] [File: https://api.swaggerhub.com/domains/Plattform_i40/Part1-MetaModel-Schemas/V3.0RC02] The field 'paths' in 'document' object is REQUIRED. [#/paths]
fail: Microsoft.OpenApi.Hidi.Handlers.TransformCommandHandler[0]
      => Parsing OpenAPI: https://api.swaggerhub.com/apis/Plattform_i40/AssetAdministrationShell-Environment/V1.0RC03 => Detected errors
      Detected error during parsing: [File: https://api.swaggerhub.com/domains/Plattform_i40/Part2-API-Schemas/V1.0RC03] The field 'paths' in 'document' object is REQUIRED. [#/paths]

Part1-MetaModel-Schemas and Part2-API-Schemas do not contain "paths". Is that intentional, and is it valid OpenAPI?

On this website I'm reading "The OpenAPI document MUST contain at least one paths field".

@arteeh
Copy link

arteeh commented Sep 23, 2024

Hi @sebbader-sap sorry for the ping. I wonder if you've seen my question above?

@sebbader-sap
Copy link
Contributor

Hi @arteeh, honestly, I saw it some time ago but simply hadn't any time to dig into it. However, we just noticed two nasty bugs in the V3.0.2_xyz versions. Can you try again with the (not yet officially released but already available) V3.0.3_xyz files?

@arteeh
Copy link

arteeh commented Sep 24, 2024

I think your bugfix did not affect my problem.

Some more testing with the latest yaml's in the main branch:

NSwag Studio stumbles over escape sequences in 'pattern' (line 182) in part 1 (not sure why it says JSON, the app says I can input YAML which I did. Maybe it internally converts to JSON first):

Newtonsoft.Json.JsonReaderException: Bad JSON escape sequence: \x. Path 'components.schemas.Blob.allOf[1].properties.contentType.allOf[2].pattern', line 1, position 6395.

In Kiota I still get the paths error I mentioned:

kiota generate -l CSharp -o ./GeneratedIDTApi -n Beenen.MS.IDTApi -d https://raw.githubusercontent.com/admin-shell-io/aas-specs-api/refs/heads/main/Part1-MetaModel-Schemas/openapi.yaml -c Client --exclude-backward-compatible --log-level Information --co

Output:

info: Kiota.Builder.KiotaBuilder[0]
      Cleaning output directory C:\Users\madejong\Git\NXTGEN\Beenen.MS.IDTApi\.\GeneratedIDTApi
info: Kiota.Builder.KiotaBuilder[0]
      loaded description from remote source
warn: Kiota.Builder.KiotaBuilder[0]
      OpenAPI warning: #/ - A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter.
fail: Kiota.Builder.KiotaBuilder[0]
      OpenAPI error: #/paths - The field 'paths' in 'document' object is REQUIRED.
warn: Kiota.Builder.KiotaBuilder[0]
      No server url found in the OpenAPI document. The base url will need to be set when using the client.
info: Kiota.Builder.KiotaBuilder[0]
      loaded description from remote source
Generation completed successfully

kiota generate -l CSharp -o ./GeneratedIDTApi -n Beenen.MS.IDTApi -d https://raw.githubusercontent.com/admin-shell-io/aas-specs-api/refs/heads/main/Part2-API-Schemas/openapi.yaml -c Client --exclude-backward-compatible --log-level Information --co

Output:

info: Kiota.Builder.KiotaBuilder[0]
      Cleaning output directory C:\Users\madejong\Git\NXTGEN\Beenen.MS.IDTApi\.\GeneratedIDTApi
info: Kiota.Builder.KiotaBuilder[0]
      loaded description from remote source
warn: Kiota.Builder.KiotaBuilder[0]
      OpenAPI warning: #/ - [File: https://api.swaggerhub.com/domains/Plattform_i40/Part1-MetaModel-Schemas/V3.0.3] A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter.
warn: Kiota.Builder.KiotaBuilder[0]
      OpenAPI warning: #/ - [File: https://api.swaggerhub.com/domains/Plattform_i40/Part1-MetaModel-Schemas/V3.0.1] A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter.
warn: Kiota.Builder.KiotaBuilder[0]
      OpenAPI warning: #/ - A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter.
warn: Kiota.Builder.KiotaBuilder[0]
      OpenAPI warning: #/ - The schema SubmodelElementValue is a polymorphic type but does not define a discriminator. This will result in a serialization errors.
warn: Kiota.Builder.KiotaBuilder[0]
      OpenAPI warning: #/components/schemas/ServiceDescription/properties/profiles/items/example - Data and type mismatch found.
fail: Kiota.Builder.KiotaBuilder[0]
      OpenAPI error: #/paths - [File: https://api.swaggerhub.com/domains/Plattform_i40/Part1-MetaModel-Schemas/V3.0.3] The field 'paths' in 'document' object is REQUIRED.
fail: Kiota.Builder.KiotaBuilder[0]
      OpenAPI error: #/paths - [File: https://api.swaggerhub.com/domains/Plattform_i40/Part1-MetaModel-Schemas/V3.0.1] The field 'paths' in 'document' object is REQUIRED.
fail: Kiota.Builder.KiotaBuilder[0]
      OpenAPI error: #/paths - The field 'paths' in 'document' object is REQUIRED.
warn: Kiota.Builder.KiotaBuilder[0]
      No server url found in the OpenAPI document. The base url will need to be set when using the client.
info: Kiota.Builder.KiotaBuilder[0]
      loaded description from remote source
Generation completed successfully

They say 'generation completed successfully' but the output folder just has an empty useless client in it.

Jetbrains Rider also has a code generator feature, tried that one on part 1 and it also gets stuck on paths:

Exception in thread "main" org.openapitools.codegen.SpecValidationException: There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-validate-spec (CLI).
 | Error count: 1, Warning count: 68
Errors: 
	-attribute paths is missing
Warnings: 
	-attribute paths is missing

	at org.openapitools.codegen.config.CodegenConfigurator.toContext(CodegenConfigurator.java:717)
	at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:744)
	at org.openapitools.codegen.cmd.Generate.execute(Generate.java:527)
	at org.openapitools.codegen.cmd.OpenApiGeneratorCommand.run(OpenApiGeneratorCommand.java:32)
	at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:66)

When I manually run the underlying command with --skip-validate-spec I actually get promising code (only had to make a few manual changes to get it to build).

It does choke when I GET an AAS from my BaSyx server due to a "type": null in a submodel reference where I think it should say ExternalReference or ModelReference. AasCore C# library errors on this as well, so I think that's a BaSyx problem, not an IDTA problem.

@sebbader-sap
Copy link
Contributor

@juileetikekar and @aorzelskiGH can you help here?

@sebbader-sap
Copy link
Contributor

I could imagine that the code generator has a problem as sometimes two or more regex patterns are valid for one string field and maybe the generator only expects zero or one...

@sebbader-sap
Copy link
Contributor

NSwag Studio stumbles over escape sequences in 'pattern' (line 182) in part 1 (not sure why it says JSON, the app says I can input YAML which I did.

I guess it transforms the YAML first into JSON and then proceeds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants