microsoft / kiota

OpenAPI based HTTP Client code generator
https://aka.ms/kiota/docs
MIT License
2.92k stars 202 forks source link

Sending files to API #5638

Open connorjjarvis opened 4 days ago

connorjjarvis commented 4 days ago

Issue I'm encountering an issue when sending a file to the API using Kiota. The error message returned is: Expected a MultiPartBody instance, but got UploadCsvPostRequestBody

The UploadCsvPostRequestBody class only has a string File property.

Has anyone managed to send a file via Kiota and can help me out here?

Code Snippet

    public async Task LoadFiles(InputFileChangeEventArgs e)
{
            using var stream = uploadedFile.OpenReadStream();
            using var memoryStream = new MemoryStream();
            await stream.CopyToAsync(memoryStream);
            var fileContent = memoryStream.ToArray();

            var base64File = Convert.ToBase64String(fileContent);

            var body = new UploadCsvPostRequestBody() { File = base64File };

            var response = await client.WorkItems.UploadCsv.PostAsync(body);
    }

API Endpoint

    [HttpPost(ApiRoutes.WorkItem.UploadCsv.Path)]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [Consumes("multipart/form-data", "text/csv")]
    public async Task<ActionResult<CsvUploadResult>> UploadCsv(IFormFile? file)
baywet commented 4 days ago

Hi @connorjjarvis Thank you for using kiota and for reaching out.

Which version of kiota was used to generate this client?

If not 1.19.1, please upgrade kiota and update the generated client.

More context https://github.com/microsoft/kiota/discussions/5545

connorjjarvis commented 4 days ago

After installing the version 1.19.1 (Tool 'microsoft.openapi.kiota' was reinstalled with the stable version (version '1.19.1').)

And this bundle: Image

Rerunning the Kiota generate command: dotnet kiota generate -l CSharp -c ApiClient -n Api -d https://localhost:5001/swagger/v1/swagger.json -o ./ -b

No changes were made to the files and the problem is still happening for me, I'll retry it all again in the morning (UK Time) to see if I missed something

baywet commented 4 days ago

Thank you for the additional information.

Can you please share your OpenAPI description? or a minimal reproduction description if it's large?

connorjjarvis commented 3 days ago

I've reduced it down quite a bit, here is the OpenAPI spec

OpenAPI Spec

``` { "openapi": "3.0.1", "info": { "title": "Howden Pipelines Web API 1.0", "version": "1.0" }, "paths": { "/workItems": { "get": { "tags": [ "WorkItem" ], "parameters": [ { "name": "Page", "in": "query", "schema": { "maximum": 2147483647, "minimum": 1, "type": "integer", "format": "int32" } }, { "name": "PageSize", "in": "query", "schema": { "maximum": 2147483647, "minimum": 1, "type": "integer", "format": "int32" } }, { "name": "Search", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkItemDtoPagedResponse" } } } } } } }, "/workItems/{guid}": { "get": { "tags": [ "WorkItem" ], "parameters": [ { "name": "guid", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkItemDto" } } } }, "404": { "description": "Not Found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } } } } }, "/workItems/uploadCsv": { "post": { "tags": [ "WorkItem" ], "requestBody": { "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary" } } }, "encoding": { "file": { "style": "form" } } }, "text/csv": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary" } } }, "encoding": { "file": { "style": "form" } } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CsvUploadResult" } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } } } } } }, "components": { "schemas": { "CsvError": { "type": "object", "properties": { "Row": { "type": "integer", "format": "int32" }, "Column": { "type": "string", "nullable": true }, "Error": { "type": "string", "nullable": true } }, "additionalProperties": false }, "CsvUploadResult": { "type": "object", "properties": { "IsSuccess": { "type": "boolean", "readOnly": true }, "Errors": { "type": "array", "items": { "$ref": "#/components/schemas/CsvError" }, "nullable": true }, "Count": { "type": "integer", "format": "int32" } }, "additionalProperties": false }, "ProblemDetails": { "type": "object", "properties": { "type": { "type": "string", "nullable": true }, "title": { "type": "string", "nullable": true }, "status": { "type": "integer", "format": "int32", "nullable": true }, "detail": { "type": "string", "nullable": true }, "instance": { "type": "string", "nullable": true } }, "additionalProperties": {} }, "WorkItemDto": { "required": [ "Description", "Guid", "LockedBy", "Status", "UpdatedAt" ], "type": "object", "properties": { "Guid": { "type": "string", "format": "uuid" }, "Description": { "type": "string", "nullable": true }, "LockedBy": { "type": "string", "nullable": true }, "UpdatedAt": { "type": "string", "format": "date-time", "nullable": true }, "Status": { "type": "string", "nullable": true } }, "additionalProperties": false }, "WorkItemDtoPagedResponse": { "type": "object", "properties": { "Page": { "type": "integer", "format": "int32" }, "PageSize": { "type": "integer", "format": "int32" }, "TotalCount": { "type": "integer", "format": "int32" }, "TotalPages": { "type": "integer", "format": "int32" }, "Data": { "type": "array", "items": { "$ref": "#/components/schemas/WorkItemDto" }, "nullable": true }, "HasPreviousPage": { "type": "boolean", "readOnly": true }, "HasNextPage": { "type": "boolean", "readOnly": true } }, "additionalProperties": false } } } } ```

On this endpoint here: "/workItems/uploadCsv" when Kiota generates this, it wants us to send it as a UploadCsvPostRequestBody with the property "File" as a string.

baywet commented 2 days ago

Thank you for the additional information.

For others reading this, here is a smaller repro

{
    "openapi": "3.0.1",
    "info": {
        "title": "Howden Pipelines Web API 1.0",
        "version": "1.0",
        "description": "goo"
    },
    "servers": [
        {
            "url": "https://localhost:5001",
            "description": "Localhost"
        }
    ],
    "paths": {
        "/workItems/uploadCsv": {
            "post": {
                "tags": [
                    "WorkItem"
                ],
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary"
                                    }
                                }
                            },
                            "encoding": {
                                "file": {
                                    "style": "form"
                                }
                            }
                        },
                        "text/csv": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary"
                                    }
                                }
                            },
                            "encoding": {
                                "file": {
                                    "style": "form"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CsvUploadResult"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "CsvError": {
                "type": "object",
                "properties": {
                    "Row": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "Column": {
                        "type": "string",
                        "nullable": true
                    },
                    "Error": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "additionalProperties": false
            },
            "CsvUploadResult": {
                "type": "object",
                "properties": {
                    "IsSuccess": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "Errors": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CsvError"
                        },
                        "nullable": true
                    },
                    "Count": {
                        "type": "integer",
                        "format": "int32"
                    }
                },
                "additionalProperties": false
            }
        }
    }
}
baywet commented 2 days ago

I was able to reproduce the issue and put together #5639 to address it.