micro-elements / MicroElements.Swashbuckle.FluentValidation

Use FluentValidation rules instead of ComponentModel attributes
MIT License
379 stars 60 forks source link

Property of type IFormFile is nullable even with NotEmpty rule #131

Open icnocop opened 1 year ago

icnocop commented 1 year ago

Hi.

If I have an action which accepts a model decorated with FromForm which contains a property of type IFormFile which has a NotEmpty rule, the OpenAPI schema is generated and unexpectedly has nullable: true on that property.

I expected the property to not be nullable because of the NotEmpty rule.

It may be related to https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/issues/24

See https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/pull/130

The unit test in IFormFileTests passes successfully, but when I view the swagger UI or generated swagger.json of the UploadFile action in SampleNSwagWebApi, nullable is set to true.

image

image

Thank you.

petriashev commented 1 year ago

Hi Rami I have looked at this case. Swachbuckle and NSwag do form-data processing with other filter type. I've created a prototype for Swashbuckle and will do the same for NSwag

icnocop commented 1 year ago

Thank you.

As a work-around, I created a document processor for NSwag:

    using System.Linq;
    using NJsonSchema;
    using NSwag.Generation.Processors;
    using NSwag.Generation.Processors.Contexts;

    public class FormFileSchemaProcessor : IDocumentProcessor
    {
        private const string MultipartFormData = "multipart/form-data";

        public void Process(DocumentProcessorContext context)
        {
            foreach (var (_, operation) in context.Document.Paths.SelectMany(x => x.Value))
            {
                var requestBody = operation.RequestBody;
                if (requestBody == null)
                {
                    continue;
                }

                if (!requestBody.Content.ContainsKey(MultipartFormData))
                {
                    continue;
                }

                var multipartFormData = requestBody.Content[MultipartFormData];
                foreach (var property in multipartFormData.Schema.Properties)
                {
                    var propertyValue = property.Value;
                    if ((propertyValue.Type == JsonObjectType.String)
                        && (propertyValue.Format == JsonFormatStrings.Binary))
                    {
                        propertyValue.IsRequired = true;
                    }
                }
            }
        }
    }

In Startup.cs:

services.AddOpenApiDocument((settings, serviceProvider) =>
{
    ...
    settings.DocumentProcessors.Add(new FormFileSchemaProcessor());
});
molekp commented 1 year ago

Hi,

I also have same issue, but I'm using Swacsbuckle.

To reproduce it you can simply copy FilesController from SampleNSwagWebApi to SampleWebApi and start SampleWebApi. You will get similar results: image

    "/api/Files/UploadFile": {
      "post": {
        "tags": [
          "Files"
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "File": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              },
              "encoding": {
                "File": {
                  "style": "form"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    }

Thank you