RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.8k stars 1.3k forks source link

Int Array not working with FormData #1840

Open cruiserkernan opened 5 years ago

cruiserkernan commented 5 years ago

If I use an array of integer in formdata i receive a 400 error ["The value '"1","2"' is not valid."]} This happens when i try the api from the Swagger UI.

Anyone knows if this is a bug or if I am misssing something?

RicoSuter commented 5 years ago

With a client generated with the C# generator? Or how to do you get this request?

cruiserkernan commented 5 years ago

We are using aspNetCoreToSwagger and in startup running useSwagger3UI. The swagger specification is generated with nswag.MSBuild.

This is the generated specification for this parameter:

         {
            "type": "array",
            "name": "ids",
            "in": "formData",
            "collectionFormat": "multi",
            "x-nullable": false,
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },

I am testing the api using swagger UI. image

This generates the request for this int array parameter as: "1","2"

This is the nswag-file:

{
  "runtime": "NetCore21",
  "defaultVariables": null,
  "swaggerGenerator": {
    "aspNetCoreToSwagger": {
      "project": "Web.csproj",
      "msBuildProjectExtensionsPath": null,
      "configuration": null,
      "runtime": null,
      "targetFramework": "",
      "noBuild": true,
      "verbose": false,
      "workingDirectory": null,
      "requireParametersWithoutDefault": false,
      "apiGroupNames": null,
      "defaultPropertyNameHandling": "CamelCase",
      "defaultReferenceTypeNullHandling": "NotNull",
      "defaultEnumHandling": "Integer",
      "flattenInheritanceHierarchy": false,
      "generateKnownTypes": true,
      "generateXmlObjects": false,
      "generateAbstractProperties": false,
      "ignoreObsoleteProperties": false,
      "allowReferencesWithProperties": false,
      "excludedTypeNames": [],
      "serviceHost": null,
      "serviceBasePath": null,
      "serviceSchemes": [],
      "infoTitle": "***",
      "infoDescription": null,
      "infoVersion": "1.0.0",
      "documentTemplate": null,
      "documentProcessorTypes": [],
      "operationProcessorTypes": [],
      "typeNameGeneratorType": null,
      "schemaNameGeneratorType": null,
      "contractResolverType": null,
      "serializerSettingsType": null,
      "useDocumentProvider": false,
      "documentName": "v1",
      "aspNetCoreEnvironment": null,
      "createWebHostBuilderMethod": null,
      "startupType": null,
      "allowNullableBodyParameters": true,
      "output": "******",
      "outputType": "Swagger2",
      "assemblyPaths": [],
      "assemblyConfig": null,
      "referencePaths": [],
      "useNuGetCache": false
    }
  },
  "codeGenerators": {
    "swaggerToTypeScriptClient": {
      "className": "{controller}Client",
      "moduleName": "",
      "namespace": "",
      "typeScriptVersion": 2.7,
      "template": "Fetch",
      "promiseType": "Promise",
      "httpClass": "Http",
      "useSingletonProvider": false,
      "injectionTokenType": "OpaqueToken",
      "rxJsVersion": 5.0,
      "dateTimeType": "MomentJS",
      "nullValue": "Undefined",
      "generateClientClasses": true,
      "generateClientInterfaces": false,
      "generateOptionalParameters": false,
      "exportTypes": true,
      "wrapDtoExceptions": false,
      "clientBaseClass": null,
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "protectedMethods": [],
      "configurationClass": null,
      "useTransformOptionsMethod": false,
      "useTransformResultMethod": false,
      "generateDtoTypes": true,
      "operationGenerationMode": "MultipleClientsFromOperationId",
      "markOptionalProperties": false,
      "generateCloneMethod": false,
      "typeStyle": "Interface",
      "classTypes": [],
      "extendedClasses": [],
      "extensionCode": null,
      "generateDefaultValues": true,
      "excludedTypeNames": [],
      "handleReferences": false,
      "generateConstructorInterface": true,
      "convertConstructorInterfaceData": false,
      "importRequiredTypes": true,
      "useGetBaseUrlMethod": false,
      "baseUrlTokenName": "API_BASE_URL",
      "queryNullValue": "",
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": "*****"
    }
  }
}

Let me know if you need any more information.

Thanks

RicoSuter commented 5 years ago

To me this looks more like a Swagger UI 3 bug (which is only bundled into nswag but an external project)

cruiserkernan commented 5 years ago

I forgot to mention that the same happens when using the api from the generated typescript clients.

Could it be a bug related to dotnet core 2.2?

RicoSuter commented 5 years ago

Not sure if this feature is already supported in the typescript/c# generators... what is the output for this operation?

cruiserkernan commented 5 years ago

This is the generated typscript for the controller.

update(ids: number[] | undefined): Promise<Item> {
        let url_ = this.baseUrl + "/api/item/update";
        url_ = url_.replace(/[?&]$/, "");

        const content_ = new FormData();  

        if (ids === null || ids === undefined)
            throw new Error("The parameter 'ids' cannot be null.");
        else
            content_.append("ids", ids.toString());

        let options_ = <RequestInit>{
                    body: content_,
                    method: "POST",
                    headers: {
                        "Accept": "application/json"
                    }
                };

                return this.http.fetch(url_, options_).then((_response: Response) => {
                    return this.processUpdate(_response);
                });
    }
cslovell commented 5 years ago

I'm having the same issue--when using curl to POST, it works, yet the swagger form (identical to the one posted above) generated by UseSwaggerUi3 does not pass the integer array. Wonder if there are any known workarounds.