Skip to content

Commit

Permalink
fix required handling for formdata properties
Browse files Browse the repository at this point in the history
  • Loading branch information
Kirk Munro authored and Kirk Munro committed Oct 7, 2024
1 parent 7d6df3a commit 33b2101
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,21 @@ public class CaseAttachmentModel

public IFormFile Contents { get; set; }
}

[HttpPost("UploadAttachment2")]
public Task<IActionResult> UploadAttachment2(
[FromForm][Required] CaseAttachmentModel2 model,
[Required] IFormFile contents)
{
return Task.FromResult<IActionResult>(Ok());
}

public class CaseAttachmentModel2
{
[Required]
public string Title { get; init; }

public int? MessageId { get; set; }
}
}
}
51 changes: 51 additions & 0 deletions src/NSwag.Generation.AspNetCore.Tests/Parameters/FormDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,56 @@ public async Task WhenOperationHasFormDataComplex_ThenItIsInRequestBody()
}
},".Replace("\r", ""), json.Replace("\r", ""));
}

[Fact]
public async Task WhenOperationHasFormDataComplexWithRequiredProperties_ThenItIsInRequestBody()
{
// Arrange
var settings = new AspNetCoreOpenApiDocumentGeneratorSettings
{
SchemaSettings = new NewtonsoftJsonSchemaGeneratorSettings
{
SchemaType = SchemaType.OpenApi3
}
};

// Act
var document = await GenerateDocumentAsync(settings, typeof(FileUploadController));
var json = document.ToJson();

// Assert
var operation = document.Operations.First(o => o.Operation.OperationId == "FileUpload_UploadAttachment2").Operation;

Assert.NotNull(operation);
Assert.Contains(@"""requestBody"": {
""content"": {
""multipart/form-data"": {
""schema"": {
""type"": ""object"",
""required"": [
""Title"",
""contents""
],
""properties"": {
""Title"": {
""type"": ""string"",
""nullable"": false
},
""MessageId"": {
""type"": ""integer"",
""format"": ""int32"",
""nullable"": true
},
""contents"": {
""type"": ""string"",
""format"": ""binary"",
""nullable"": false
}
}
}
}
}
},".Replace("\r", ""), json.Replace("\r", ""));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,18 @@ private JsonSchema CreateOrGetFormDataSchema(OperationProcessorContext context)
return requestBody.Content[MultipartFormData].Schema;
}

private static JsonSchemaProperty CreateFormDataProperty(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, JsonSchema schema)
private JsonSchemaProperty CreateFormDataProperty(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, JsonSchema schema)
{
return context.SchemaGenerator.GenerateWithReferenceAndNullability<JsonSchemaProperty>(
var formDataProperty = context.SchemaGenerator.GenerateWithReferenceAndNullability<JsonSchemaProperty>(
extendedApiParameter.ApiParameter.Type.ToContextualType(extendedApiParameter.Attributes), context.SchemaResolver);

var contextualPropertyType = extendedApiParameter.ParameterType.ToContextualType();
var typeDescription = _settings.SchemaSettings.ReflectionService.GetDescription(contextualPropertyType, _settings.SchemaSettings);
var isRequired = extendedApiParameter.IsRequired(_settings.RequireParametersWithoutDefault);
formDataProperty.IsRequired = isRequired;
formDataProperty.IsNullableRaw = _settings.AllowNullableBodyParameters && !isRequired && typeDescription.IsNullable;

return formDataProperty;
}

private bool IsFileArray(Type type, JsonTypeDescription typeInfo)
Expand Down Expand Up @@ -527,7 +535,7 @@ public bool IsRequired(bool requireParametersWithoutDefault)
// available in asp.net core >= 2.2
if (ApiParameter.HasProperty("IsRequired"))
{
isRequired = ApiParameter.TryGetPropertyValue("IsRequired", false);
isRequired = ApiParameter.TryGetPropertyValue("IsRequired", false) || ApiParameter.ModelMetadata?.IsRequired == true;
}
else
{
Expand All @@ -538,7 +546,6 @@ public bool IsRequired(bool requireParametersWithoutDefault)
}
else if (ApiParameter.ModelMetadata != null &&
ApiParameter.ModelMetadata.IsBindingRequired)

{
isRequired = true;
}
Expand Down

0 comments on commit 33b2101

Please sign in to comment.