swagger-api / swagger-api/swagger-codegen

swagger-codegen (c#) issue (or misuse ?) for file upload in a POST Web API operation

Open
#2,175 24 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Client: C-Sharp Issue: Bug Issue: Workaround available
Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

I have a developed a Swagger-Api with a "File" Controller exposing a POST "Upload" operation.
If I upload a file from the Swagger UI, it is correctly uploaded by the "File" Controller.
I then have generated a C# API client class with swagger-codegen. (v2.1.5)
The generated FileApi client class exposes a public async System.Threading.Tasks.Task<ApiResponse<Object>> FileUploadAsyncWithHttpInfo(Stream file) method.
When I call the FileApi.FileUploadAsyncWithHttpInfo(stream) method of the generated Api class, I get an System.AggregateException: "One or more errors occured".
The unique inner exception is a IO.Swagger.Client.ApiException: "Error calling FileUpload: The request was aborted."
The stream is a MemoryStream copied from an open FileStream.
I get with the debugger in the FileApi class to see what happens:

Here is the final lines of the

public async System.Threading.Tasks.Task<ApiResponse<Object>> FileUploadAsyncWithHttpInfo (Stream file)
{
    .
    .
    .

    // make the HTTP request
    IRestResponse response = (IRestResponse) await Configuration.ApiClient.CallApiAsync(path_, Method.POST, queryParams, postBody, headerParams, formParams, fileParams, pathParams);

    int statusCode = (int) response.StatusCode;

    if (statusCode >= 400)
        throw new ApiException (statusCode, "Error calling LelPublishPackage: " + response.Content, response.Content);
    else if (statusCode == 0)
        throw new ApiException (statusCode, "Error calling LelPublishPackage: " + response.ErrorMessage, response.ErrorMessage);

    return new ApiResponse<Object>(statusCode,
        response.Headers.ToDictionary(x => x.Name, x => x.Value.ToString()),
        (Object) Configuration.ApiClient.Deserialize(response, typeof(Object)));
}

When calling the CallApiAsync method, the parameters values are the following:

path_: "/api/Files"
Method.POST: POST
queryParams: Count = 0
postBody: null
headerParams: Count = 1 / [0]: {[Accept, application/json]}
formParams: Count = 0
fileParams: Count = 1 / [0]: {[file, RestSharp.FileParameter]} 
pathParams: Count = 1 / [0]: {[format, json]}

After calling the CallApiAsync method, the returned response.StatusCode is 0, its response.Status is Aborted and its response.ErrorMessage is "The request was aborted."
Thus, an ApiException is thrown.

If I get into the CallApiAsync() method, the code is:

public async System.Threading.Tasks.Task<Object> CallApiAsync(
    String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody,
    Dictionary<String, String> headerParams, Dictionary<String, String> formParams,
    Dictionary<String, FileParameter> fileParams, Dictionary<String, String> pathParams)
{
    var request = PrepareRequest(
        path, method, queryParams, postBody, headerParams, formParams, fileParams, pathParams);
    var response = await RestClient.ExecuteTaskAsync(request);
    return (Object)response;
}

The request is prepared and the the RestClient.ExecuteTaskAsync(request) method is called.
The returned response has its StatusCode set to 0, its response.Status is Aborted and its response.ErrorMessage is "The request was aborted."

Do I do something wrong ?

Is there an issue in the swagger-code generated client FileApi class ?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the generated FileApi.FileUploadAsyncWithHttpInfo method and follow its call into ApiClient.CallApiAsync, PrepareRequest, and RestClient.ExecuteTaskAsync. Reproduce the upload using the supplied MemoryStream and inspect why the response is aborted with status code 0. Done means determining whether the generated client or its use is responsible and documenting or testing the resulting fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.