Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
141 stars 166 forks source link

System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. #142

Open crafty615 opened 6 years ago

crafty615 commented 6 years ago

Not getting any useful information in the stacktrace. Cannot seem to figure out what exactly is causing the key not found exception.

output:

PS C:\Users\User\Documents\NSwagStuff> autorest readme.md --debug
AutoRest code generation utility [version: 2.0.4262; node: v8.9.4]
(C) 2018 Microsoft Corporation.
https://aka.ms/autorest
Network Enabled: true
Starting @microsoft.azure/autorest-core from C:\Users\User\.autorest\@microsoft.azure_autorest-core@2.0.4262
   Loading AutoRest core      'C:\Users\User\.autorest\@microsoft.azure_autorest-core@2.0.4262\node_modules\@microsoft.azure\autorest-core\dist' (2.0.4262)
   Loading AutoRest extension '@microsoft.azure/autorest.csharp' (~2.2.51->2.2.57)
   Loading AutoRest extension '@microsoft.azure/autorest.modeler' (2.3.43->2.3.43)
DEBUG: swagger-document-override/md-override-loader - START
DEBUG: swagger-document/loader - START
DEBUG: pipeline-emitter - START
DEBUG: configuration-emitter - START
DEBUG: Emitting 'pipeline' at file:///C:/Users/User/Documents/NSwagStuff/GeneratedRest/pipeline
DEBUG: Emitting 'configuration' at file:///C:/Users/User/Documents/NSwagStuff/GeneratedRest/configuration
DEBUG: pipeline-emitter - END
DEBUG: configuration-emitter - END
DEBUG: swagger-document-override/md-override-loader - END
DEBUG: swagger-document/loader - END
DEBUG: swagger-document/individual/transform - START
DEBUG: swagger-document/individual/transform - END
DEBUG: swagger-document/individual/schema-validator - START
DEBUG: swagger-document/individual/schema-validator - END
DEBUG: swagger-document/individual/identity - START
DEBUG: swagger-document/individual/identity - END
DEBUG: swagger-document/compose - START
DEBUG: swagger-document/compose - END
DEBUG: swagger-document/transform-immediate - START
DEBUG: swagger-document/transform-immediate - END
DEBUG: swagger-document/transform - START
DEBUG: swagger-document/transform - END
DEBUG: swagger-document/identity - START
DEBUG: swagger-document/identity - END
DEBUG: openapi-document/openapi-document-converter - START
DEBUG: swagger-document/emitter - START
DEBUG: Emitting 'swagger-document' at file:///C:/Users/User/Documents/NSwagStuff/GeneratedRest/nswagproofswagger
DEBUG: swagger-document/emitter - END
DEBUG: openapi-document/openapi-document-converter - END
DEBUG: openapi-document/transform - START
DEBUG: openapi-document/transform - END
DEBUG: openapi-document/component-modifiers - START
DEBUG: openapi-document/component-modifiers - END
DEBUG: openapi-document/identity - START
DEBUG: openapi-document/identity - END
DEBUG: csharp/imodeler1 - START
DEBUG: openapi-document/emitter - START
DEBUG: Emitting 'openapi-document' at file:///C:/Users/User/Documents/NSwagStuff/GeneratedRest/nswagproofswagger
DEBUG: openapi-document/emitter - END
FATAL: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
   at System.ThrowHelper.ThrowKeyNotFoundException()
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at AutoRest.Modeler.SwaggerModeler.Build(ServiceDefinition serviceDefinition) in C:\Users\ci\AppData\Local\Temp\PUBLISHu1dw1\43_20171213T192246\autorest.modeler\src\SwaggerModeler.cs:line 128
   at AutoRest.Modeler.Program.<ProcessInternal>d__2.MoveNext() in C:\Users\ci\AppData\Local\Temp\PUBLISHu1dw1\43_20171213T192246\autorest.modeler\src\Program.cs:line 60
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NewPlugin.<Process>d__15.MoveNext()
FATAL: csharp/imodeler1 - FAILED
FATAL: Error: Plugin imodeler1 reported failure.
Process() cancelled due to exception : Plugin imodeler1 reported failure.
  Error: Plugin imodeler1 reported failure.

Readme.md:

# AutoRest swagger generation
> see https://aka.ms/autorest 

## config

yaml
input-file: nswagproofswagger.json
output-folder: ./GeneratedRest

csharp:
    namespace: NSwagProof.WebServiceTests.GeneratedClient
    sync-methods: all
    use-datetimeoffset: true

Swagger Json input:

NSwag Swagger Json

``` { "x-generator": "NSwag v11.16.1.0 (NJsonSchema v9.10.41.0 (Newtonsoft.Json v9.0.0.0))", "swagger": "2.0", "info": { "title": "NSwagProof.WebService", "version": "1.0.0" }, "host": "localhost:8100", "schemes": [ "http" ], "consumes": [ "application/json" ], "produces": [ "application/json" ], "paths": { "/animals": { "get": { "tags": [ "Animal" ], "summary": "Gets all animals", "operationId": "Animal_GetAllAnimals", "responses": { "200": { "x-nullable": true, "description": "List of Animals", "schema": { "type": "array", "items": { "$ref": "#/definitions/Animal" } } } } }, "post": { "tags": [ "Animal" ], "summary": "Adds an Animal", "operationId": "Animal_AddAnimal", "consumes": [ "application/json" ], "parameters": [ { "name": "Animal", "in": "body", "required": true, "schema": { "$ref": "#/definitions/Animal" } } ], "responses": { "200": { "x-nullable": true, "description": "Animal", "schema": { "$ref": "#/definitions/Animal" } } } } }, "/animals/{id}": { "get": { "tags": [ "Animal" ], "summary": "Gets a specific animal", "operationId": "Animal_GetAnimal", "parameters": [ { "type": "integer", "name": "id", "in": "path", "required": true, "description": "Animal's ID", "format": "int32", "x-nullable": false } ], "responses": { "200": { "x-nullable": true, "description": "Animal", "schema": { "$ref": "#/definitions/Animal" } } } }, "put": { "tags": [ "Animal" ], "summary": "Updates an Animal", "operationId": "Animal_UpdateAnimal", "consumes": [ "application/json" ], "parameters": [ { "type": "integer", "name": "id", "in": "path", "required": true, "description": "Animal's ID", "format": "int32", "x-nullable": false }, { "name": "Animal", "in": "body", "required": true, "schema": { "$ref": "#/definitions/Animal" } } ], "responses": { "200": { "x-nullable": true, "description": "Animal", "schema": { "$ref": "#/definitions/Animal" } } } } }, "/test/ping": { "get": { "tags": [ "Test" ], "summary": "Pings server side and returns a 200", "operationId": "Test_Ping", "responses": { "200": { "x-nullable": true, "description": "200 OK", "schema": { "type": "file" } } } } }, "/test/post": { "post": { "tags": [ "Test" ], "summary": "Tests the Swagger body param attribute with a type not initially registered", "operationId": "Test_PostBodyTest", "consumes": [ "application/json" ], "parameters": [ { "name": "RandomTestContainer", "in": "body", "required": true, "schema": { "title": "RandomTestContainer", "type": "object", "description": "Random container object for a test", "required": [ "Thing" ], "properties": { "Thing": { "type": "integer", "description": "Thing that does things", "format": "int32" } } } } ], "responses": { "200": { "x-nullable": true, "description": "", "schema": { "type": "string" } } } } } }, "definitions": { "Animal": { "type": "object", "discriminator": "AnimalType", "description": "Animal Base Class", "required": [ "NumberOfLegs", "IsDomesticated", "Diet", "IsExtinct", "AnimalType" ], "properties": { "Id": { "type": "integer", "description": "Identifier", "format": "int32" }, "Species": { "type": "string", "description": "Animals species scientific name" }, "NumberOfLegs": { "type": "integer", "description": "Amount of legs the animal has", "format": "int32" }, "IsDomesticated": { "type": "boolean", "description": "States whether the animal has been domesticated as a pet" }, "Diet": { "description": "What type of food the animal eats", "allOf": [ { "$ref": "#/definitions/Diet" } ] }, "IsExtinct": { "type": "boolean", "description": "Whether there are any of the same animal still alive" }, "AnimalType": { "type": "string" } } }, "Diet": { "type": "string", "description": "What the animal eats", "x-enumNames": [ "Omnivorous", "Carnivorous", "Herbivorous" ], "enum": [ "Omnivorous", "Carnivorous", "Herbivorous" ] }, "Cat": { "type": "object", "description": "Cat Class", "required": [ "IsHairless" ], "properties": { "Breed": { "type": "string", "description": "What type of cat" }, "IsHairless": { "type": "boolean", "description": "Whether the cat has hair or not" } }, "allOf": [ { "$ref": "#/definitions/DomesticatedAnimal" } ] }, "DomesticatedAnimal": { "type": "object", "discriminator": "AnimalType", "description": "Domesticated Animal Base Class", "required": [ "Size", "AnimalType" ], "properties": { "Name": { "type": "string", "description": "Name of the Animal" }, "Size": { "description": "Size of the animal", "allOf": [ { "$ref": "#/definitions/Size" } ] }, "Allergies": { "type": "array", "description": "Allergies the animal may have", "items": { "$ref": "#/definitions/Allergy" } }, "AnimalType": { "type": "string" } }, "allOf": [ { "$ref": "#/definitions/Animal" } ] }, "Size": { "type": "string", "description": "Size of the Animal", "x-enumNames": [ "Tiny", "Small", "Medium", "Large", "Huge" ], "enum": [ "Tiny", "Small", "Medium", "Large", "Huge" ] }, "Allergy": { "type": "object", "description": "Allergy Class", "properties": { "Name": { "type": "string", "description": "Name of the Allergy" }, "DictionaryThing": { "type": "object", "description": "Dictionary to tests swagger stuff", "additionalProperties": { "type": "integer", "format": "int32" } } } }, "Dog": { "type": "object", "description": "Dog Class", "required": [ "IsAGoodBoy" ], "properties": { "Breed": { "type": "string", "description": "The type of dog" }, "IsAGoodBoy": { "type": "boolean", "description": "Whether the dog is a good boy or not. (He is)" } }, "allOf": [ { "$ref": "#/definitions/DomesticatedAnimal" } ] }, "Chupacabra": { "type": "object", "description": "Chupacabra Class", "required": [ "NumberOfGoatsSlaughtered" ], "properties": { "NumberOfGoatsSlaughtered": { "type": "integer", "description": "Number of goats the Chupacabra has slaughtered", "format": "int32" } }, "allOf": [ { "$ref": "#/definitions/Animal" } ] } } } ```

pdylanross commented 6 years ago

I'm working with crafty on this and I was able to get the client to generate after some debugging. What I found is that autorest doesn't like how we're generating enums with nswag. I'm not 100% familiar with the swagger spec - is the generated swagger for enums in that spec valid? Should this be a bug report to NSwag instead?

The results of the debugging was that with current master of the modeler project it's blowing up on line 142 of SwaggerModeler.cs:

objectType.BaseModelType = GeneratedTypes[ExtendedTypes[typeName]];

The extended types dict maps the type name from Animal_Diet to Diet, however the generated types dict only contains a def for Animal_Diet. The same happens to the size enum. I did not dig in much further than that.

fearthecowboy commented 6 years ago

The swagger looks valid.

we don't support x-enumNames -- but that shouldn't cause anything to blow up.

You can add x-ms-enum definitions, (which is required to get generated classes for enums in AutoRest) .. see : http://azure.github.io/autorest/extensions/#x-ms-enum

mrcunninghamz commented 4 years ago

I'm working with crafty on this and I was able to get the client to generate after some debugging. What I found is that autorest doesn't like how we're generating enums with nswag. I'm not 100% familiar with the swagger spec - is the generated swagger for enums in that spec valid? Should this be a bug report to NSwag instead?

The results of the debugging was that with current master of the modeler project it's blowing up on line 142 of SwaggerModeler.cs:

objectType.BaseModelType = GeneratedTypes[ExtendedTypes[typeName]];

The extended types dict maps the type name from Animal_Diet to Diet, however the generated types dict only contains a def for Animal_Diet. The same happens to the size enum. I did not dig in much further than that.

I am running into a similar issue, is there anything that can be done to avoid this? Is this a problem with the swagger definition?

mrcunninghamz commented 4 years ago

I found the answer to my issue in this thread. Using a config.yaml to change my swagger document's references to the enums in a way that autorest will be happy about.

https://github.com/Azure/autorest/issues/3417