swagger-api / swagger-api/swagger-codegen
[Typescript-Angular] Multipart doesn't appear to handle DTOs properly
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
Backend is aspnetcore.
DTOs are not being serialized at all when in a multipart request body.
If doing something like this
public async Task<IActionResult> AddNewTemplateVersionAsync(
[FromRoute] Guid templateId,
[FromForm] VersionDataDto versionData,
[FromForm] IFormFile pdfFile)
{}
I would expect that versionData would be added to the formParams and JSON.stringified, however in this case the dto object is broken up into individual properies as is the file. And nothing is stringified.
If instead this is done
public async Task<IActionResult> AddNewTemplateVersionAsync(
[FromRoute] Guid templateId,
[FromBody] VersionDataDto versionData,
[FromForm] IFormFile pdfFile)
{}
only the dto object shows up in the generated call, the file is ignored. Basically bodyParam is given preference.
If [FromBody] is left out then the dto is assumed to be a query parameter when it isn't and it isn't stringified anyway. The file is however included as the formParams and passed in the body.
My current minor fix for this is to modify the mustache template so that in the case of formParams and a bodyParam, the bodyParam is stringified and added to the formParams, and the order of operations in the http request is flipped so that formParams take precedence over the bodyParam, as body will be included in formParams if both exist. This obviously doesn't fix any of the generated swagger, only the end client calls. Ideally a fix would address all parts.
Swagger-codegen version
3.0.34
Steps to reproduce
Make an api endpoint that utilizes multipart/form-data, e.g. it takes a File, also have it take some DTO. Maybe for the pet store sample project there's an endpoint that allows for an image to be uploaded at the same time a pet object is added, have these in the same api.
Related issues/PRs
Seems related to https://github.com/swagger-api/swagger-codegen/issues/9139
Suggest a fix/enhancement
Modification that allows for the use of FromBody and FromForm in same endpoint. The bodyParam should be appended to the formParams and serialized/stringified, the formParams should take preference in the http request eg.
{{#formParams}}
{{#isListContainer}}
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
{{paramName}}.forEach((element) => {
{{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', <any>element){{#useHttpClient}} || formParams{{/useHttpClient}};
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
{{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])){{#useHttpClient}} || formParams{{/useHttpClient}};
{{/isCollectionFormatMulti}}
}
{{/isListContainer}}
{{^isListContainer}}
if ({{paramName}} !== undefined) {
{{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', <any>{{paramName}}){{#useHttpClient}} || formParams{{/useHttpClient}};
}
{{/isListContainer}}
{{/formParams}}
{{#bodyParam}}
if ({{paramName}} !== undefined && {{paramName}} !== null) {
{{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', JSON.stringify({{paramName}}));
}
{{/bodyParam}}
{{/hasFormParams}}
{{#useHttpClient}}
return this.httpClient.{{httpMethod}}{{^isResponseFile}}<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>{{/isResponseFile}}(`${this.basePath}{{{path}}}`,{{#isBodyAllowed}}
{{#hasFormParams}}convertFormParamsToString ? formParams.toString() : formParams{{/hasFormParams}}{{^hasFormParams}}{{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}{{/hasFormParams}},{{/isBodyAllowed}}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the multipart/form-data case with an ASP.NET Core endpoint containing both a DTO and an IFormFile, then inspect the TypeScript-Angular Mustache templates that assemble formParams and bodyParam. Compare the behavior with related issue #9139. Done means the generated client includes the file and JSON-stringifies the DTO in the multipart request, while generated Swagger remains consistent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, typescript
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100