diff --git a/src/NSwag.CodeGeneration.CSharp.Tests/BinaryTests.cs b/src/NSwag.CodeGeneration.CSharp.Tests/BinaryTests.cs index 16e3e4860..cf3271c8d 100644 --- a/src/NSwag.CodeGeneration.CSharp.Tests/BinaryTests.cs +++ b/src/NSwag.CodeGeneration.CSharp.Tests/BinaryTests.cs @@ -55,6 +55,64 @@ public async Task When_body_is_binary_then_stream_is_used_as_parameter_in_CSharp CSharpCompiler.AssertCompile(code); } + [Fact] + public async Task When_body_is_binary_then_IFormFile_is_used_as_part_of_object_in_CSharp_ASPNETCore() + { + var yaml = @"openapi: 3.0.0 +servers: + - url: https://www.example.com/ +info: + version: '2.0.0' + title: 'Test API' +paths: + /files: + post: + tags: + - Files + summary: 'Add File' + operationId: addFile + responses: + '200': + description: 'something' + content: + application/json: + schema: + $ref: '#/components/schemas/FileToken' + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + name: + type: string +components: + schemas: + FileToken: + type: object + required: + - fileId + properties: + fileId: + type: string + format: uuid"; + + var document = await OpenApiYamlDocument.FromYamlAsync(yaml); + + // Act + CSharpControllerGeneratorSettings settings = new CSharpControllerGeneratorSettings(); + settings.ControllerTarget = CSharpControllerTarget.AspNetCore; + var codeGenerator = new CSharpControllerGenerator(document, settings); + var code = codeGenerator.GenerateFile(); + + // Assert + await VerifyHelper.Verify(code); + CSharpCompiler.AssertCompile(code); + } + [Fact] public async Task When_body_is_binary_then_IFormFile_is_used_as_parameter_in_CSharp_ASPNETCore() { diff --git a/src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/BinaryTests.When_body_is_binary_then_IFormFile_is_used_as_part_of_object_in_CSharp_ASPNETCore.verified.txt b/src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/BinaryTests.When_body_is_binary_then_IFormFile_is_used_as_part_of_object_in_CSharp_ASPNETCore.verified.txt new file mode 100644 index 000000000..31b1f49d4 --- /dev/null +++ b/src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/BinaryTests.When_body_is_binary_then_IFormFile_is_used_as_part_of_object_in_CSharp_ASPNETCore.verified.txt @@ -0,0 +1,81 @@ + + +namespace MyNamespace +{ + using System = global::System; + + public interface IController + { + + + + + System.Threading.Tasks.Task AddFileAsync(Microsoft.AspNetCore.Http.IFormFile file, string name); + + } + + + public partial class Controller : Microsoft.AspNetCore.Mvc.ControllerBase + { + private IController _implementation; + + public Controller(IController implementation) + { + _implementation = implementation; + } + + [Microsoft.AspNetCore.Mvc.HttpPost, Microsoft.AspNetCore.Mvc.Route("files")] + public System.Threading.Tasks.Task AddFile(Microsoft.AspNetCore.Http.IFormFile file, string name) + { + + return _implementation.AddFileAsync(file, name); + } + + } + + public partial class FileToken + { + + [Newtonsoft.Json.JsonProperty("fileId", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + public System.Guid FileId { get; set; } + + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + + public partial class FileParameter + { + public FileParameter(System.IO.Stream data) + : this (data, null, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName) + : this (data, fileName, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName, string contentType) + { + Data = data; + FileName = fileName; + ContentType = contentType; + } + + public System.IO.Stream Data { get; private set; } + + public string FileName { get; private set; } + + public string ContentType { get; private set; } + } + + +} diff --git a/src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs b/src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs index cb9cc8071..1fe7d0a8a 100644 --- a/src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs +++ b/src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs @@ -264,36 +264,36 @@ protected override string ResolveParameterType(OpenApiParameter parameter) { if (schema.Type == JsonObjectType.Array && schema.Item.IsBinary) { - return controllerSettings.ControllerTarget == CSharpControllerTarget.AspNetCore ? - "System.Collections.Generic.ICollection" : - "System.Collections.Generic.ICollection"; + return ResolveControllerBinaryCollectionType(controllerSettings); } - else - { - return controllerSettings.ControllerTarget == CSharpControllerTarget.AspNetCore ? - "Microsoft.AspNetCore.Http.IFormFile" : - "System.Web.HttpPostedFileBase"; - } - } - else - { - return parameter.HasBinaryBodyWithMultipleMimeTypes ? "FileParameter" : "System.IO.Stream"; + + return ResolveControllerBinarySingleType(controllerSettings); } + + return parameter.HasBinaryBodyWithMultipleMimeTypes ? "FileParameter" : "System.IO.Stream"; } if (schema.Type == JsonObjectType.Array && (schema.Item?.IsBinary ?? false)) { - return "System.Collections.Generic.IEnumerable"; + return _settings is CSharpControllerGeneratorSettings controllerSettings + ? ResolveControllerBinaryCollectionType(controllerSettings) + : "System.Collections.Generic.IEnumerable"; } if (schema.IsBinary) { if (parameter.CollectionFormat == OpenApiParameterCollectionFormat.Multi && !schema.Type.HasFlag(JsonObjectType.Array)) { - return "System.Collections.Generic.IEnumerable"; + return _settings is CSharpControllerGeneratorSettings controllerSettings + ? ResolveControllerBinaryCollectionType(controllerSettings) + : "System.Collections.Generic.IEnumerable"; + } + else + { + return _settings is CSharpControllerGeneratorSettings controllerSettings + ? ResolveControllerBinarySingleType(controllerSettings) + : "FileParameter"; } - - return "FileParameter"; } return base.ResolveParameterType(parameter) @@ -301,6 +301,20 @@ protected override string ResolveParameterType(OpenApiParameter parameter) .Replace(_settings.CSharpGeneratorSettings.DictionaryType + "<", _settings.ParameterDictionaryType + "<"); } + private static string ResolveControllerBinarySingleType(CSharpControllerGeneratorSettings controllerSettings) + { + return controllerSettings.ControllerTarget == CSharpControllerTarget.AspNetCore ? + "Microsoft.AspNetCore.Http.IFormFile" : + "System.Web.HttpPostedFileBase"; + } + + private static string ResolveControllerBinaryCollectionType(CSharpControllerGeneratorSettings controllerSettings) + { + return controllerSettings.ControllerTarget == CSharpControllerTarget.AspNetCore ? + "System.Collections.Generic.ICollection" : + "System.Collections.Generic.ICollection"; + } + /// Creates the response model. /// The operation. /// The status code.