ASP.Net Core File badly handled in csharp-dotnet2 client

Open
#9,723 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

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

Research direction

Start with the csharp-dotnet2 generated client and trace ApiClient.CallApi through ApiClient.Deserialize for a response declared as type file. Reproduce the GetVersionFile request using the supplied Swagger definition and generation command with a ZIP containing a NUL byte. Done means the generated client preserves the complete binary response instead of truncating it at the NUL.

Written by the indexing model from the issue text.

Description

Description

Code for downloading files generated by swagger-codegen (csharp) is wrong. It may work in most cases, but it cuts my .zip file after \0.

Code generated with swagger-codegen:

        public System.IO.Stream GetVersionFile (int? versionId)
        {
            // verify the required parameter 'versionId' is set
            if (versionId == null) throw new ApiException(400, "Missing required parameter 'versionId' when calling GetVersionFile");
    
            var path = "/api/Versions/{versionId}/File";
            path = path.Replace("{format}", "json");
            path = path.Replace("{" + "versionId" + "}", ApiClient.ParameterToString(versionId));
    
            var queryParams = new Dictionary<String, String>();
            var headerParams = new Dictionary<String, String>();
            var formParams = new Dictionary<String, String>();
            var fileParams = new Dictionary<String, FileParameter>();
            String postBody = null;
    
                                                    
            // authentication setting, if any
            String[] authSettings = new String[] { "Bearer" };
    
            // make the HTTP request
            IRestResponse response = (IRestResponse) ApiClient.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
    
            if (((int)response.StatusCode) >= 400)
                throw new ApiException ((int)response.StatusCode, "Error calling GetVersionFile: " + response.Content, response.Content);
            else if (((int)response.StatusCode) == 0)
                throw new ApiException ((int)response.StatusCode, "Error calling GetVersionFile: " + response.ErrorMessage, response.ErrorMessage);
    
            return (System.IO.Stream) ApiClient.Deserialize(response.Content, typeof(System.IO.Stream), response.Headers);
        }

response.Length has bigger value than response.Content.Length because there is a \0 in my .zip file. Then the response.Content is passed to File.WriteAllText. There is no length specified so my file is smaller than it is supposed to be. It's a easy fix in generated code, but it's a huge waste of time to do this every time after generating the client code.

Swagger-codegen version

swagger-codegen-cli-3.0.11

Swagger declaration file content or url

(for YAML code) or

...
			"get": {
				"tags": [ "Applications" ],
				"summary": "Version file download",
				"operationId": "GetVersionFile",
				"consumes": [],
				"produces": [ "application/octet-stream" ],
				"parameters": [
					{
						"name": "versionId",
						"in": "path",
						"description": "Version ID",
						"required": true,
						"type": "integer",
						"format": "int32"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"schema": { "type": "file" }
					}
				}
			}
...
Command line used for generation

java -jar swagger-codegen-cli-3.0.11.jar generate -l csharp-dotnet2 -i http://localhost:9220/swagger/v2/swagger.json

Steps to reproduce

Create a controler in ASP.Net Core that returns File. Example:

	[HttpGet("Versions/{versionId}/File")]
	[Produces("application/octet-stream")]
	[ProducesResponseType(200, Type = typeof(FileStreamResult))]
	public async Task<IActionResult> GetVersionFile(int versionId)
	{
		try
		{
			ApplicationVersion applicationVersion = await ApplicationService.GetVersion(versionId);
			var stream = await ApplicationService.GetVersionFileStream(versionId);
			return File(stream, "application/octet-stream", applicationVersion.FileName);
		}
		catch (InvalidOperationException)
		{
			return NotFound();
		}
	}

Add mapping in startup.

...
	c.MapType<FileStreamResult>(() => new Schema { Type = "file" });
...

Generate csharp-dotnet2 client and run your method.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

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.

More from swagger-api/swagger-codegen

All issues in swagger-api/swagger-codegen

Similar issues

More Backend & API Design issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.