Skip to content

Commit 895e0ca

Browse files
committed
Improve form data handling
1 parent 45cc9fc commit 895e0ca

File tree

6 files changed

+72
-8
lines changed

6 files changed

+72
-8
lines changed

src/NSwag.CodeGeneration.CSharp/Models/CSharpOperationModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@ protected override string ResolveParameterType(OpenApiParameter parameter)
252252
}
253253
}
254254

255+
if (schema.Type == JsonObjectType.Array && schema.Item.IsBinary)
256+
{
257+
return "System.Collections.Generic.IEnumerable<FileParameter>";
258+
}
259+
255260
if (schema.IsBinary)
256261
{
257262
if (parameter.CollectionFormat == OpenApiParameterCollectionFormat.Multi && !schema.Type.HasFlag(JsonObjectType.Array))

src/NSwag.CodeGeneration.TypeScript/Models/TypeScriptOperationModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ protected override string ResolveParameterType(OpenApiParameter parameter)
168168
}
169169

170170
var schema = parameter.ActualSchema;
171+
if (schema.Type == JsonObjectType.Array && schema.Item.IsBinary)
172+
{
173+
return "FileParameter[]";
174+
}
175+
171176
if (schema.IsBinary)
172177
{
173178
if (parameter.CollectionFormat == OpenApiParameterCollectionFormat.Multi && !schema.Type.HasFlag(JsonObjectType.Array))

src/NSwag.CodeGeneration/Models/OperationModelBase.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public TParameterModel ContentParameter
206206
public bool HasAcceptHeaderParameterParameter => HeaderParameters.Any(p => p.Name.ToLowerInvariant() == "accept");
207207

208208
/// <summary>Gets a value indicating whether the operation has form parameters.</summary>
209-
public bool HasFormParameters => _operation.ActualParameters.Any(p => p.Kind == OpenApiParameterKind.FormData);
209+
public bool HasFormParameters => Parameters.Any(p => p.Kind == OpenApiParameterKind.FormData);
210210

211211
/// <summary>Gets a value indicating whether the operation consumes 'application/x-www-form-urlencoded'.</summary>
212212
public bool ConsumesFormUrlEncoded =>
@@ -229,10 +229,10 @@ public TParameterModel ContentParameter
229229
public bool IsDeprecated => _operation.IsDeprecated;
230230

231231
/// <summary>Gets or sets a value indicating whether this operation has an XML body parameter.</summary>
232-
public bool HasXmlBodyParameter => _operation.ActualParameters.Any(p => p.IsXmlBodyParameter);
232+
public bool HasXmlBodyParameter => Parameters.Any(p => p.IsXmlBodyParameter);
233233

234234
/// <summary>Gets or sets a value indicating whether this operation has an binary body parameter.</summary>
235-
public bool HasBinaryBodyParameter => _operation.ActualParameters.Any(p => p.IsBinaryBodyParameter);
235+
public bool HasBinaryBodyParameter => Parameters.Any(p => p.IsBinaryBodyParameter);
236236

237237
/// <summary>Gets the mime type of the request body.</summary>
238238
public string Consumes
@@ -331,9 +331,28 @@ protected virtual string ResolveParameterType(OpenApiParameter parameter)
331331
/// <returns>The parameters.</returns>
332332
protected IList<OpenApiParameter> GetActualParameters()
333333
{
334-
return _operation.ActualParameters
334+
var parameters = _operation.ActualParameters
335335
.Where(p => !_settings.ExcludedParameterNames.Contains(p.Name))
336336
.ToList();
337+
338+
var formDataSchema = _operation?.RequestBody?.Content?["multipart/form-data"]?.Schema;
339+
if (formDataSchema != null)
340+
{
341+
var formDataProperties = formDataSchema.ActualProperties.ToList();
342+
return parameters.Where(p => !p.IsBinaryBodyParameter).Concat(formDataProperties.Select((p, i) => new OpenApiParameter
343+
{
344+
Name = p.Key,
345+
Kind = OpenApiParameterKind.FormData,
346+
Schema = p.Value,
347+
CollectionFormat = p.Value.Type.HasFlag(JsonObjectType.Array) && p.Value.Item != null ?
348+
OpenApiParameterCollectionFormat.Multi : OpenApiParameterCollectionFormat.Undefined,
349+
//Explode = p.Value.Type.HasFlag(JsonObjectType.Array) && p.Value.Item != null,
350+
//Schema = p.Value.Type.HasFlag(JsonObjectType.Array) && p.Value.Item != null ? p.Value.Item : p.Value,
351+
Position = parameters.Count + 100 + i
352+
})).ToList();
353+
}
354+
355+
return parameters;
337356
}
338357
}
339358
};

src/NSwag.CodeGeneration/Models/ParameterModelBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ public IEnumerable<PropertyModel> CollectionPropertyNames
146146
/// <summary>Gets a value indicating whether this is an XML body parameter.</summary>
147147
public bool IsXmlBodyParameter => _parameter.IsXmlBodyParameter;
148148

149+
/// <summary>Gets a value indicating whether this is an binary body parameter.</summary>
150+
public bool IsBinaryBodyParameter => _parameter.IsBinaryBodyParameter;
151+
149152
/// <summary>Gets a value indicating whether the parameter is of type date.</summary>
150153
public bool IsDate =>
151154
Schema.Format == JsonFormatStrings.Date &&
@@ -165,7 +168,7 @@ public IEnumerable<PropertyModel> CollectionPropertyNames
165168
public bool IsStringArray => IsArray && Schema.Item?.ActualSchema.Type.HasFlag(JsonObjectType.String) == true;
166169

167170
/// <summary>Gets a value indicating whether this is a file parameter.</summary>
168-
public bool IsFile => Schema.IsBinary;
171+
public bool IsFile => Schema.IsBinary || (IsArray && Schema?.Item?.IsBinary == true);
169172

170173
/// <summary>Gets a value indicating whether the parameter is a binary body parameter.</summary>
171174
public bool IsBinaryBody => _parameter.IsBinaryBodyParameter;

src/NSwag.Generation.AspNetCore.Tests.Web/Controllers/Parameters/FileUploadController.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,18 @@ namespace NSwag.Generation.AspNetCore.Tests.Web.Controllers.Parameters
1010
[Route("api/[controller]")]
1111
public class FileUploadController : Controller
1212
{
13-
[HttpPost]
13+
[HttpPost("UploadFile")]
1414
public ActionResult UploadFile([NotNull] IFormFile file, [FromForm, NotNull]string test)
1515
{
1616
return Ok();
1717
}
1818

19+
[HttpPost("UploadFiles")]
20+
public ActionResult UploadFiles([NotNull, FromForm] IFormFile[] files, [FromForm, NotNull]string test)
21+
{
22+
return Ok();
23+
}
24+
1925
[HttpPost("UploadAttachment")]
2026
public async Task<IActionResult> UploadAttachment(
2127
[FromRoute][Required] string caseId,

src/NSwag.Generation.AspNetCore.Tests/Parameters/FileUploadTests.cs renamed to src/NSwag.Generation.AspNetCore.Tests/Parameters/FormDataTests.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace NSwag.Generation.AspNetCore.Tests.Parameters
88
{
9-
public class FileUploadTests : AspNetCoreTestsBase
9+
public class FormDataTests : AspNetCoreTestsBase
1010
{
1111
[Fact]
1212
public async Task WhenOperationHasFormDataFile_ThenItIsInRequestBody()
@@ -24,8 +24,34 @@ public async Task WhenOperationHasFormDataFile_ThenItIsInRequestBody()
2424

2525
Assert.Equal("binary", schema.Properties["file"].Format);
2626
Assert.Equal(JsonObjectType.String, schema.Properties["file"].Type);
27-
2827
Assert.Equal(JsonObjectType.String, schema.Properties["test"].Type);
28+
29+
Assert.Contains(@" ""/api/FileUpload/UploadFiles"": {
30+
""post"": {
31+
""tags"": [
32+
""FileUpload""
33+
],
34+
""operationId"": ""FileUpload_UploadFiles"",
35+
""requestBody"": {
36+
""content"": {
37+
""multipart/form-data"": {
38+
""schema"": {
39+
""properties"": {
40+
""files"": {
41+
""type"": ""array"",
42+
""items"": {
43+
""type"": ""string"",
44+
""format"": ""binary""
45+
}
46+
},
47+
""test"": {
48+
""type"": ""string""
49+
}
50+
}
51+
}
52+
}
53+
}
54+
},", json);
2955
}
3056

3157
[Fact]

0 commit comments

Comments
 (0)