Handling file upload in ASP.NET Core 5 with Swagger UI
Image from Pexels by Anete Lusina

Handling file upload in ASP.NET Core 5 with Swagger UI

Generating proper file upload in Swagger UI for file upload in ASP.NET Core 5

In 2019 I worked on a REST API service which accepts files and stores them. Back then in .NET Core 2.2 I wrote custom Swagger operation filter which I described in article Handling file uploads in Swagger UI with ASP.NET Core. Since then two new major releases of .NET Core were published, 3.0 and 5.0 and it was the time to upgrade the service to latest 5.0 version of ASP.NET Core.

However there were some obsolete methods which were no longer supported in new framework so they had to be rewritten. One among these was Swagger operation filter responsible for proper file upload representation in Swagger UI.

In case you do not want to go through the old, obsolete article from 2019 I mentioned above, I will briefly describe the the problem here and finally provide new operation filter for latest Swagger UI for .NET Core 5.0.

The problem

To describe the problem I used a simple sample web api with one controller and with only one controller method only for uploading the file

    [ApiController]
    [Route("[controller]")]
    public class DocumentsController : ControllerBase
    {

        [HttpPost]
        public async Task<IActionResult> UploadDocument(
            [FromHeader] String documentType,
            [FromForm] IFormFile file
            )
        {
            // TODO: handle file upload
            return await Task.FromResult(Ok());
        }
    }
    

This is how you would typically add file as a parameter for upload to an API endpoint in ASP.NET Core controller method. However, when you run this from your IDE you will get the following UI representation in Swagger UI.

File Upload Core 5

As you can see, file upload is not properly represented in the Swagger UI which makes testing of this endpoint pretty much impossible directly from the Swagger UI directly and in order to test it you would have to use POSTMAN or CURL.

Ideally we should have a file upload control here so we can pick the file from he local machine and test the endpoint. This is where custom Swagger operation filter comes into play. We'll intercept SwaggerGen OAS generation process via our custom IOperationFilter implementation to describe this endpoint properly and render out the proper UI.

Swagger file upload operation filter

If you look at this endpoint and potentially any endpoint you may have for uploading the files in your Web API, you will notice that at least one of the parameters, specifically the one that carries the file content is of type IFormFile. We can use this to identify the file upload methods and alter them.

After we apply this condition in our filter, we just need to alter the operation parameter schema properties with the new ones that indicate the binary content.

    public class SwaggerFileOperationFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var fileUploadMime = "multipart/form-data";
            if (operation.RequestBody == null || !operation.RequestBody.Content.Any(x => x.Key.Equals(fileUploadMime, StringComparison.InvariantCultureIgnoreCase)))
                return;

            var fileParams = context.MethodInfo.GetParameters().Where(p => p.ParameterType == typeof(IFormFile));
            operation.RequestBody.Content[fileUploadMime].Schema.Properties =
                fileParams.ToDictionary(k => k.Name, v => new OpenApiSchema()
                {
                    Type = "string",
                    Format = "binary"
                });
        }
    }
    

The only thing left is to plug in this operation class to our Web API DI container registration in Startup.cs 

        public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Sample.FileUpload.Api", Version = "v1" });
                c.OperationFilter<SwaggerFileOperationFilter>();
            });
        }
    

Now once we start the service and access the Swagger UI, we'll get the proper UI and you can select the file from local machine and test the endpoint directly from Swagger UI.

File Upload Core 5 Filter

References

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform including ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article